<commit_before>var assert = require('assert');
var http   = require('http');
var nock   = require('nock');
var ytdl   = require('..');

var videos = [
  'http://www.youtube.com/watch?v=qQ31INpjXX0',
  'http://www.youtube.com/watch?v=pJk0p-98Xzc',
  'http://www.youtube.com/watch?v=mgOS64BF2eU',
  'http://www.youtube.com/watch?v=qQ31INpjXX0',
  'http://www.youtube.com/watch?v=mvuqS0nxFvA'
];

describe('Try downloading videos without mocking', function() {
  before(function() {
    nock.restore();
  });

  videos.forEach(function(video) {
    describe(video, function() {
      it('Request status code is 200', function(done) {
        ytdl.getInfo(video, { downloadURL: true }, function(err, info) {
          if (err) return done(err);

          var url = info.formats[0].url;
          var req = http.get(url, function(res) {
            assert.equal(res.statusCode, 200);
            res.on('error', done);
            req.abort();
            done();
          });
          req.on('error', done);
        });
      });
    });
  });
});
<commit_msg>some videos use 302<commit_after>var assert = require('assert');
var http   = require('http');
var nock   = require('nock');
var ytdl   = require('..');

var videos = [
  'http://www.youtube.com/watch?v=qQ31INpjXX0',
  'http://www.youtube.com/watch?v=pJk0p-98Xzc',
  'http://www.youtube.com/watch?v=mgOS64BF2eU',
  'http://www.youtube.com/watch?v=qQ31INpjXX0',
  'http://www.youtube.com/watch?v=mvuqS0nxFvA'
];

describe('Try downloading videos without mocking', function() {
  before(function() {
    nock.restore();
  });

  videos.forEach(function(video) {
    describe(video, function() {
      it('Request status code is not 403 Forbidden', function(done) {
        ytdl.getInfo(video, { downloadURL: true }, function(err, info) {
          if (err) return done(err);

          var url = info.formats[0].url;
          var req = http.get(url, function(res) {
            assert.notEqual(res.statusCode, 403);
            res.on('error', done);
            req.abort();
            done();
          });
          req.on('error', done);
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>var keyboard = effroi.keyboard,
    assert = chai.assert;

// Helper
var elt, evts=[], listeners=[];
function regEventListener(elt, type, capture, stop, prevent) {
  var listener=function(e) {
    if(e.type!=type) {
      throw 'Event types differs.'
    }
    evts.push({
      type : e.type,
      target : e.target,
      currentTarget : e.currentTarget,
      clientX : e.clientX,
      clientY : e.clientY,
      altKey : e.altKey,
      ctrlKey : e.ctrlKey,
      shiftKey : e.shiftKey,
      metaKey : e.metaKey,
      button : e.button,
      buttons : e.buttons,
      pointerType : e.pointerType,
      charCode : e.charCode,
      char : e.char,
      view : e.view,
      relatedTarget : e.relatedTarget
    });
    if(stop) {
      e.stopPropagation();
    }
    if(prevent) {
      e.preventDefault();
    }
  };
  elt.addEventListener(type, listener, capture);
  listeners.push({
    elt: elt,
    type: type,
    listener : listener,
    capture : capture
  });
}

function init(innerHTML) {
  elt = document.createElement('div');
  elt.innerHTML = innerHTML || 'foo';
  document.body.appendChild(elt);
}

function uninit() {
  document.body.removeChild(elt);
  for(var i=listeners.length-1; i>=0; i--) {
    listeners[i].elt.removeEventListener(
    listeners[i].type, listeners[i].listener, listeners[i].capture);
  }
  evts=[];
  elt=null;
}

describe("Keyboard device", function() {

    describe("hit a key when on an element", function() {

        before(function() {
            init();
            regEventListener(document.activeElement, 'keydown');
            regEventListener(document.activeElement, 'keypress');
            regEventListener(document.activeElement, 'keyup');

        });

        after(uninit);

        it("should return true", function() {
            assert.equal(keyboard.hit('a'.charCodeAt(0)), true);
        });

        it("should set the char and charcode property", function() {
            assert.equal(evts[0].char, 'a');
        });

        it("should set the view property to window", function() {
            assert.equal(evts[0].view, window);
        });

        it("should set the special key property to false", function() {
            assert.equal(evts[0].ctrlKey, false);
            assert.equal(evts[0].altKey, false);
            assert.equal(evts[0].shiftKey, false);
            assert.equal(evts[0].metaKey, false);
        });

        it("should trigger a keydown event on the activeElement", function() {
            assert.equal(evts[0].type, 'keydown');
            assert.equal(evts[0].target, document.activeElement);
        });

        it("should trigger a keypress event on the element", function() {
            assert.equal(evts[1].type, 'keypress');
            assert.equal(evts[1].target, document.activeElement);
        });

        it("should trigger a keyup event on the element", function() {
            assert.equal(evts[2].type, 'keyup');
            assert.equal(evts[2].target, document.activeElement);
        });

    });

    describe("hit a key when on an input element", function() {

        before(function() {
            init('
Text: <input type="text" value="booooooob" />
');
            elt.firstChild.firstChild.lastChild.focus();
            regEventListener(elt.firstChild.firstChild.lastChild, 'keydown');
            regEventListener(elt.firstChild.firstChild.lastChild, 'keypress');
            regEventListener(elt.firstChild.firstChild.lastChild, 'keyup');
            regEventListener(document.body, 'keydown');
            regEventListener(document.body, 'keypress');
            regEventListener(document.body, 'keyup');

        });

        after(uninit);

        it("should return true", function() {
            assert.equal(keyboard.hit('a'.charCodeAt(0)), true);
        });

        it("should set the char property correctly", function() {
            assert.equal(evts[0].char, 'a');
        });

        it("should set the view property to window", function() {
            assert.equal(evts[0].view, window);
        });

        it("should change its value", function() {
            assert.equal(elt.firstChild.firstChild.lastChild.value, 'boooooooba');
        });

        it("should set the special key property to false", function() {
            assert.equal(evts[0].ctrlKey, false);
            assert.equal(evts[0].altKey, false);
            assert.equal(evts[0].shiftKey, false);
            assert.equal(evts[0].metaKey, false);
        });

        it("should trigger a keydown event on the activeElement", function() {
            assert.equal(evts[0].type, 'keydown');
            assert.equal(evts[0].target, elt.firstChild.firstChild.lastChild);
            assert.equal(evts[0].currentTarget, elt.firstChild.firstChild.lastChild);
        });

        it("should bubble the keydown event on the parent", function() {
            assert.equal(evts[1].type, 'keydown');
            assert.equal(evts[1].target, elt.firstChild.firstChild.lastChild);
            assert.equal(evts[1].currentTarget, document.body);
        });

        it("should trigger a keypress event on the element", function() {
            assert.equal(evts[2].type, 'keypress');
            assert.equal(evts[2].target, elt.firstChild.firstChild.lastChild);
            assert.equal(evts[2].currentTarget, elt.firstChild.firstChild.lastChild);
        });

        it("should bubble the keypress event on the parent", function() {
            assert.equal(evts[3].type, 'keypress');
            assert.equal(evts[3].target, elt.firstChild.firstChild.lastChild);
            assert.equal(evts[3].currentTarget, document.body);
        });

        it("should trigger a keyup event on the element", function() {
            assert.equal(evts[4].type, 'keyup');
            assert.equal(evts[4].target, elt.firstChild.firstChild.lastChild);
            assert.equal(evts[4].currentTarget, elt.firstChild.firstChild.lastChild);
        });

        it("should bubble the keyup event on the parent", function() {
            assert.equal(evts[5].type, 'keyup');
            assert.equal(evts[5].target, elt.firstChild.firstChild.lastChild);
            assert.equal(evts[5].currentTarget, document.body);
        });

    });

    describe("combining ctrl + c", function() {

        before(function() {
            init();
            regEventListener(document.body, 'keydown');
            regEventListener(document.body, 'keypress');
            regEventListener(document.body, 'keyup');

        });

        after(uninit);

        it("should return true", function() {
            assert.equal(keyboard.combine(keyboard.CTRL,
              'c'.charCodeAt(0)), true);
        });

        it("should set an empty char property for the CTRL keydown event", function() {
            assert.equal(evts[0].type, 'keydown');
            assert.equal(evts[0].char, '');
        });

        it("should set the ctrlKey property for the CTRL keydown event", function() {
            (!/phantom/i.test(navigator.userAgent)) &&
            assert.equal(evts[0].ctrlKey, true);
        });

        it("should set an empty char property for the c keydown event", function() {
            assert.equal(evts[1].type, 'keydown');
            assert.equal(evts[1].char, 'c');
        });

        it("should set the ctrlKey property for the c keydown event", function() {
            (!/phantom/i.test(navigator.userAgent)) &&
            assert.equal(evts[1].ctrlKey, true);
        });

        it("should set an empty char property for the CTRL keyup event", function() {
            assert.equal(evts[2].type, 'keyup');
            assert.equal(evts[2].char, '');
        });

        it("should set the ctrlKey property for the CTRL keyup event", function() {
            (!/phantom/i.test(navigator.userAgent)) &&
            assert.equal(evts[2].ctrlKey, false);
        });

        it("should set the char property to 'c' for the c keyup event", function() {
            assert.equal(evts[3].type, 'keyup');
            assert.equal(evts[3].char, 'c');
        })

        it("should set the ctrlKey property for the c keyup event", function() {
            (!/phantom/i.test(navigator.userAgent)) &&
            assert.equal(evts[3].ctrlKey, false);
        });

    });

    describe("pasting inside an input[type=text] element where some text is selected", function() {

        before(function() {
            init('
Text: <input type="text" value="booooooob" />
');
            elt.firstChild.firstChild.lastChild.focus();
            elt.firstChild.firstChild.lastChild.selectionStart=1;
            elt.firstChild.firstChild.lastChild.selectionEnd=8;
        });

        after(uninit);

        it("should return true", function() {
          assert.equal(keyboard.paste('00'), true);
        });

        it("should change it's value", function() {
          assert.equal(elt.firstChild.firstChild.lastChild.value,'b00b');
        });

    });

    describe("pasting inside an input[type=text] element where some text is selected and the keydown event prevented", function() {

        before(function() {
            init('
Text: <input type="text" value="booooooob" />
');
            elt.firstChild.firstChild.lastChild.focus();
            elt.firstChild.firstChild.lastChild.selectionStart=1;
            elt.firstChild.firstChild.lastChild.selectionEnd=8;
            regEventListener(elt.firstChild.firstChild.lastChild,
              'keydown', false, false, true);
        });

        after(uninit);

        it("should return false", function() {
          assert.equal(
            keyboard.paste('00'),
            false);
        });

        it("should not change it's value", function() {
          assert.equal(elt.firstChild.firstChild.lastChild.value,'booooooob');
        });

    });

    describe("cutting the selected text inside an input[type=text]", function() {

        before(function() {
            init('
Text: <input type="text" value="booooooob" />
');
            elt.firstChild.firstChild.lastChild.focus();
            elt.firstChild.firstChild.lastChild.selectionStart=1;
            elt.firstChild.firstChild.lastChild.selectionEnd=8;
        });

        after(uninit);

        it("should return the cutted content", function() {
          assert.equal(keyboard.cut(),'ooooooo');
        });

        it("should change it's value", function() {
          assert.equal(elt.firstChild.firstChild.lastChild.value,'bb');
        });

    });

    describe("cutting the selected text inside an input[type=text] with a keydown event prevented", function() {

        before(function() {
            init('
Text: <input type="text" value="booooooob" />
');
            elt.firstChild.firstChild.lastChild.focus();
            elt.firstChild.firstChild.lastChild.selectionStart=1;
            elt.firstChild.firstChild.lastChild.selectionEnd=8;
            regEventListener(elt.firstChild.firstChild.lastChild,
              'keydown', false, false, true);
        });

        after(uninit);

        it("should return no content", function() {
          assert.equal(keyboard.cut(),'');
        });

        it("should not change it's value", function() {
          assert.equal(elt.firstChild.firstChild.lastChild.value,'booooooob');
        });

    });

    describe("focusing elements with the keyboard", function() {

        var previousActiveElement;

        before(function() {
            init(
                '
'
              + 'Text: <input type="text" value="text" />'
              + 'Number: <input type="number" value="1664" />'
              + 'Textarea: <textarea>Plop</textarea'
              + 'Date: <input type="date" value="" />'
              + 'Link: Link'
              + 'Button: <button label="Button"/>'
              + 'Submit: <input type="submit" value="submit" />'
              + '
'
            );
            regEventListener(document, 'keydown');
            regEventListener(document, 'keyup');
            regEventListener(elt.firstChild.firstChild.lastChild, 'blur');
            regEventListener(elt.firstChild.firstChild.lastChild, 'focus');
        });

        after(uninit);

        it("should return true", function() {
          previousActiveElement = document.activeElement;
          regEventListener(previousActiveElement, 'blur');
          regEventListener(previousActiveElement, 'focus');
          assert.equal(keyboard.focus(elt.firstChild.firstChild.lastChild), true);
        });

        it("should set the element as the active element", function() {
          assert.equal(elt.firstChild.firstChild.lastChild, document.activeElement);
        });

        it("should trigger a keydown event on the previousActiveElement", function() {
            assert.equal(evts[0].type, 'keydown');
            assert.equal(evts[0].target, previousActiveElement);
            // Seems impossible to change charCode prop with phantom
            if(!navigator.userAgent.match(/phantom/i)) {
              assert.equal(evts[0].charCode, keyboard.TAB);
            }
        });

        it("should trigger a blur event on the previousActiveElement", function() {
            assert.equal(evts[1].type, 'blur');
            assert.equal(evts[1].target, previousActiveElement);
            // Sadly, it seems impossible to set relatedTarget while using
            // the focus/blur methods. Maybe do a select() and fire focus evts
            // manually could do the job ?
            // assert.equal(evts[1].relatedTarget, elt.firstChild.firstChild.lastChild);
        });

        it("should trigger a focus event on the newly activeElement", function() {
            assert.equal(evts[2].type, 'focus');
            assert.equal(evts[2].target, elt.firstChild.firstChild.lastChild);
            // Sadly, it seems impossible to set relatedTarget while using
            // the focus/blur methods. Maybe do a select() and fire focus evts
            // manually could do the job ?
            // assert.equal(evts[2].relatedTarget, previousActiveElement);
        });

        it("should trigger a keyup event on the newlyActiveElement", function() {
            assert.equal(evts[3].type, 'keyup');
            assert.equal(evts[3].target, elt.firstChild.firstChild.lastChild);
            // Seems impossible to change charCode prop with phantom
            if(!navigator.userAgent.match(/phantom/i)) {
              assert.equal(evts[3].charCode, keyboard.TAB);
            }
        });

    });

});
<commit_msg>Ooops forgotten keyboard.js<commit_after>var keyboard = effroi.keyboard,
    assert = chai.assert;

// Helper
var elt, evts=[], listeners=[];
function regEventListener(elt, type, capture, stop, prevent) {
  var listener=function(e) {
    if(e.type!=type) {
      throw 'Event types differs.'
    }
    evts.push({
      type : e.type,
      target : e.target,
      currentTarget : e.currentTarget,
      clientX : e.clientX,
      clientY : e.clientY,
      altKey : e.altKey,
      ctrlKey : e.ctrlKey,
      shiftKey : e.shiftKey,
      metaKey : e.metaKey,
      button : e.button,
      buttons : e.buttons,
      pointerType : e.pointerType,
      charCode : e.charCode,
      char : e.char,
      view : e.view,
      relatedTarget : e.relatedTarget
    });
    if(stop) {
      e.stopPropagation();
    }
    if(prevent) {
      e.preventDefault();
    }
  };
  elt.addEventListener(type, listener, capture);
  listeners.push({
    elt: elt,
    type: type,
    listener : listener,
    capture : capture
  });
}

function init(innerHTML) {
  elt = document.createElement('div');
  elt.innerHTML = innerHTML || 'foo';
  document.body.appendChild(elt);
}

function uninit() {
  document.body.removeChild(elt);
  for(var i=listeners.length-1; i>=0; i--) {
    listeners[i].elt.removeEventListener(
    listeners[i].type, listeners[i].listener, listeners[i].capture);
  }
  evts=[];
  elt=null;
}

describe("Keyboard device", function() {

    describe("hit a key when on an element", function() {

        before(function() {
            init();
            regEventListener(document.activeElement, 'keydown');
            regEventListener(document.activeElement, 'keypress');
            regEventListener(document.activeElement, 'keyup');

        });

        after(uninit);

        it("should return true", function() {
            assert.equal(keyboard.hit('a'), true);
        });

        it("should set the char and charcode property", function() {
            assert.equal(evts[0].char, 'a');
            // Seems impossible to change charCode prop with phantom
            if(!navigator.userAgent.match(/phantom/i)) {
              assert.equal(evts[0].charCode, 'a'.charCodeAt(0));
            }
        });

        it("should set the view property to window", function() {
            assert.equal(evts[0].view, window);
        });

        it("should set the special key property to false", function() {
            assert.equal(evts[0].ctrlKey, false);
            assert.equal(evts[0].altKey, false);
            assert.equal(evts[0].shiftKey, false);
            assert.equal(evts[0].metaKey, false);
        });

        it("should trigger a keydown event on the activeElement", function() {
            assert.equal(evts[0].type, 'keydown');
            assert.equal(evts[0].target, document.activeElement);
        });

        it("should trigger a keypress event on the element", function() {
            assert.equal(evts[1].type, 'keypress');
            assert.equal(evts[1].target, document.activeElement);
        });

        it("should trigger a keyup event on the element", function() {
            assert.equal(evts[2].type, 'keyup');
            assert.equal(evts[2].target, document.activeElement);
        });

    });

    describe("hit a key when on an input element", function() {

        before(function() {
            init('
Text: <input type="text" value="booooooob" />
');
            elt.firstChild.firstChild.lastChild.focus();
            regEventListener(elt.firstChild.firstChild.lastChild, 'keydown');
            regEventListener(elt.firstChild.firstChild.lastChild, 'keypress');
            regEventListener(elt.firstChild.firstChild.lastChild, 'keyup');
            regEventListener(document.body, 'keydown');
            regEventListener(document.body, 'keypress');
            regEventListener(document.body, 'keyup');

        });

        after(uninit);

        it("should return true", function() {
            assert.equal(keyboard.hit('a'), true);
        });

        it("should set the char property correctly", function() {
            assert.equal(evts[0].char, 'a');
        });

        it("should set the view property to window", function() {
            assert.equal(evts[0].view, window);
        });

        it("should change its value", function() {
            assert.equal(elt.firstChild.firstChild.lastChild.value, 'boooooooba');
        });

        it("should set the special key property to false", function() {
            assert.equal(evts[0].ctrlKey, false);
            assert.equal(evts[0].altKey, false);
            assert.equal(evts[0].shiftKey, false);
            assert.equal(evts[0].metaKey, false);
        });

        it("should trigger a keydown event on the activeElement", function() {
            assert.equal(evts[0].type, 'keydown');
            assert.equal(evts[0].target, elt.firstChild.firstChild.lastChild);
            assert.equal(evts[0].currentTarget, elt.firstChild.firstChild.lastChild);
        });

        it("should bubble the keydown event on the parent", function() {
            assert.equal(evts[1].type, 'keydown');
            assert.equal(evts[1].target, elt.firstChild.firstChild.lastChild);
            assert.equal(evts[1].currentTarget, document.body);
        });

        it("should trigger a keypress event on the element", function() {
            assert.equal(evts[2].type, 'keypress');
            assert.equal(evts[2].target, elt.firstChild.firstChild.lastChild);
            assert.equal(evts[2].currentTarget, elt.firstChild.firstChild.lastChild);
        });

        it("should bubble the keypress event on the parent", function() {
            assert.equal(evts[3].type, 'keypress');
            assert.equal(evts[3].target, elt.firstChild.firstChild.lastChild);
            assert.equal(evts[3].currentTarget, document.body);
        });

        it("should trigger a keyup event on the element", function() {
            assert.equal(evts[4].type, 'keyup');
            assert.equal(evts[4].target, elt.firstChild.firstChild.lastChild);
            assert.equal(evts[4].currentTarget, elt.firstChild.firstChild.lastChild);
        });

        it("should bubble the keyup event on the parent", function() {
            assert.equal(evts[5].type, 'keyup');
            assert.equal(evts[5].target, elt.firstChild.firstChild.lastChild);
            assert.equal(evts[5].currentTarget, document.body);
        });

    });

    describe("combining ctrl + c", function() {

        before(function() {
            init();
            regEventListener(document.body, 'keydown');
            regEventListener(document.body, 'keypress');
            regEventListener(document.body, 'keyup');

        });

        after(uninit);

        it("should return true", function() {
            assert.equal(keyboard.combine(keyboard.CTRL, 'c'), true);
        });

        it("should set an empty char property for the CTRL keydown event", function() {
            assert.equal(evts[0].type, 'keydown');
            assert.equal(evts[0].char, '');
        });

        it("should set the ctrlKey property for the CTRL keydown event", function() {
            (!/phantom/i.test(navigator.userAgent)) &&
            assert.equal(evts[0].ctrlKey, true);
        });

        it("should set an empty char property for the c keydown event", function() {
            assert.equal(evts[1].type, 'keydown');
            assert.equal(evts[1].char, 'c');
        });

        it("should set the ctrlKey property for the c keydown event", function() {
            (!/phantom/i.test(navigator.userAgent)) &&
            assert.equal(evts[1].ctrlKey, true);
        });

        it("should set an empty char property for the CTRL keyup event", function() {
            assert.equal(evts[2].type, 'keyup');
            assert.equal(evts[2].char, '');
        });

        it("should set the ctrlKey property for the CTRL keyup event", function() {
            (!/phantom/i.test(navigator.userAgent)) &&
            assert.equal(evts[2].ctrlKey, false);
        });

        it("should set the char property to 'c' for the c keyup event", function() {
            assert.equal(evts[3].type, 'keyup');
            assert.equal(evts[3].char, 'c');
        })

        it("should set the ctrlKey property for the c keyup event", function() {
            (!/phantom/i.test(navigator.userAgent)) &&
            assert.equal(evts[3].ctrlKey, false);
        });

    });

    describe("pasting inside an input[type=text] element where some text is selected", function() {

        before(function() {
            init('
Text: <input type="text" value="booooooob" />
');
            elt.firstChild.firstChild.lastChild.focus();
            elt.firstChild.firstChild.lastChild.selectionStart=1;
            elt.firstChild.firstChild.lastChild.selectionEnd=8;
        });

        after(uninit);

        it("should return true", function() {
          assert.equal(keyboard.paste('00'), true);
        });

        it("should change it's value", function() {
          assert.equal(elt.firstChild.firstChild.lastChild.value,'b00b');
        });

    });

    describe("pasting inside an input[type=text] element where some text is selected and the keydown event prevented", function() {

        before(function() {
            init('
Text: <input type="text" value="booooooob" />
');
            elt.firstChild.firstChild.lastChild.focus();
            elt.firstChild.firstChild.lastChild.selectionStart=1;
            elt.firstChild.firstChild.lastChild.selectionEnd=8;
            regEventListener(elt.firstChild.firstChild.lastChild,
              'keydown', false, false, true);
        });

        after(uninit);

        it("should return false", function() {
          assert.equal(
            keyboard.paste('00'),
            false);
        });

        it("should not change it's value", function() {
          assert.equal(elt.firstChild.firstChild.lastChild.value,'booooooob');
        });

    });

    describe("cutting the selected text inside an input[type=text]", function() {

        before(function() {
            init('
Text: <input type="text" value="booooooob" />
');
            elt.firstChild.firstChild.lastChild.focus();
            elt.firstChild.firstChild.lastChild.selectionStart=1;
            elt.firstChild.firstChild.lastChild.selectionEnd=8;
        });

        after(uninit);

        it("should return the cutted content", function() {
          assert.equal(keyboard.cut(),'ooooooo');
        });

        it("should change it's value", function() {
          assert.equal(elt.firstChild.firstChild.lastChild.value,'bb');
        });

    });

    describe("cutting the selected text inside an input[type=text] with a keydown event prevented", function() {

        before(function() {
            init('
Text: <input type="text" value="booooooob" />
');
            elt.firstChild.firstChild.lastChild.focus();
            elt.firstChild.firstChild.lastChild.selectionStart=1;
            elt.firstChild.firstChild.lastChild.selectionEnd=8;
            regEventListener(elt.firstChild.firstChild.lastChild,
              'keydown', false, false, true);
        });

        after(uninit);

        it("should return no content", function() {
          assert.equal(keyboard.cut(),'');
        });

        it("should not change it's value", function() {
          assert.equal(elt.firstChild.firstChild.lastChild.value,'booooooob');
        });

    });

    describe("focusing elements with the keyboard", function() {

        var previousActiveElement;

        before(function() {
            init(
                '
'
              + 'Text: <input type="text" value="text" />'
              + 'Number: <input type="number" value="1664" />'
              + 'Textarea: <textarea>Plop</textarea'
              + 'Date: <input type="date" value="" />'
              + 'Link: Link'
              + 'Button: <button label="Button"/>'
              + 'Submit: <input type="submit" value="submit" />'
              + '
'
            );
            regEventListener(document, 'keydown');
            regEventListener(document, 'keyup');
            regEventListener(elt.firstChild.firstChild.lastChild, 'blur');
            regEventListener(elt.firstChild.firstChild.lastChild, 'focus');
        });

        after(uninit);

        it("should return true", function() {
          previousActiveElement = document.activeElement;
          regEventListener(previousActiveElement, 'blur');
          regEventListener(previousActiveElement, 'focus');
          assert.equal(keyboard.focus(elt.firstChild.firstChild.lastChild), true);
        });

        it("should set the element as the active element", function() {
          assert.equal(elt.firstChild.firstChild.lastChild, document.activeElement);
        });

        it("should trigger a keydown event on the previousActiveElement", function() {
            assert.equal(evts[0].type, 'keydown');
            assert.equal(evts[0].target, previousActiveElement);
            // Seems impossible to change charCode prop with phantom
            if(!navigator.userAgent.match(/phantom/i)) {
              assert.equal(evts[0].charCode,
                keyboard.KEY_TO_CHARCODE[keyboard.TAB]);
            }
        });

        it("should trigger a blur event on the previousActiveElement", function() {
            assert.equal(evts[1].type, 'blur');
            assert.equal(evts[1].target, previousActiveElement);
            // Sadly, it seems impossible to set relatedTarget while using
            // the focus/blur methods. Maybe do a select() and fire focus evts
            // manually could do the job ?
            // assert.equal(evts[1].relatedTarget, elt.firstChild.firstChild.lastChild);
        });

        it("should trigger a focus event on the newly activeElement", function() {
            assert.equal(evts[2].type, 'focus');
            assert.equal(evts[2].target, elt.firstChild.firstChild.lastChild);
            // Sadly, it seems impossible to set relatedTarget while using
            // the focus/blur methods. Maybe do a select() and fire focus evts
            // manually could do the job ?
            // assert.equal(evts[2].relatedTarget, previousActiveElement);
        });

        it("should trigger a keyup event on the newlyActiveElement", function() {
            assert.equal(evts[3].type, 'keyup');
            assert.equal(evts[3].target, elt.firstChild.firstChild.lastChild);
            // Seems impossible to change charCode prop with phantom
            if(!navigator.userAgent.match(/phantom/i)) {
              assert.equal(evts[3].charCode,
                keyboard.KEY_TO_CHARCODE[keyboard.TAB]);
            }
        });

    });

});
<|endoftext|>


<commit_before>var R = require('..');
var eq = require('./shared/eq');

var testObj = {
  a: {
    b: 2,
  },
  d: 3
};

describe('lensPath', function() {
  describe('view', function() {
    it('focuses the specified object property', function() {
      eq(R.view(R.lensPath(['d']), testObj), 3);
      eq(R.view(R.lensPath(['a', 'b']), testObj), 2);
      eq(R.view(R.lensPath([]), testObj), testObj);
    });
  });
  describe('set', function() {
    it('sets the value of the object property specified', function() {
      eq(R.set(R.lensPath(['d']), 0, testObj), {a: {b: 2}, d: 0});
      eq(R.set(R.lensPath(['a', 'b']), 0, testObj), {a: {b: 0}, d: 3});
      eq(R.set(R.lensPath([]), 0, testObj), 0);
    });
    it('adds the property to the object if it doesn\'t exist', function() {
      eq(R.set(R.lensPath('X'), 0, testObj), {a: {b: 2}, d: 3, X: 0});
      eq(R.set(R.lensPath(['a', 'X']), 0, testObj), {a: {b: 2, X: 0}, d: 3});
    });
  });
  describe('over', function() {
    it('applies function to the value of the specified object property', function() {
      eq(R.over(R.lensPath('d'), R.inc, testObj), {a: {b: 2}, d: 4});
      eq(R.over(R.lensPath(['a', 'b']), R.inc, testObj), {a: {b: 3}, d: 3});
      eq(R.over(R.lensPath([]), R.toPairs, testObj), [['a', {b: 2}], ['d', 3]]);
    });
    it('applies function to undefined and adds the property if it doesn\'t exist', function() {
      eq(R.over(R.lensPath(['X']), R.identity, testObj), {a: {b: 2}, d: 3, X: undefined});
      eq(R.over(R.lensPath(['a', 'X']), R.identity, testObj), {a: {b: 2, X: undefined}, d: 3});
    });
  });
  describe('composability', function() {
    it('can be composed', function() {
      var composedLens = R.compose(R.lensPath('a'), R.lensPath('b'));
      eq(R.view(composedLens, testObj), 2);
    });
  });
  describe('well behaved lens', function() {
    it('set s (get s) === s', function() {
      eq(R.set(R.lensPath('d'), R.view(R.lensPath('d'), testObj), testObj), testObj);
      eq(R.set(R.lensPath(['a', 'b']), R.view(R.lensPath(['a', 'b']), testObj), testObj), testObj);
    });
    it('get (set s v) === v', function() {
      eq(R.view(R.lensPath('d'), R.set(R.lensPath('d'), 0, testObj)), 0);
      eq(R.view(R.lensPath(['a', 'b']), R.set(R.lensPath(['a', 'b']), 0, testObj)), 0);
    });
    it('get (set(set s v1) v2) === v2', function() {
      var p = 'd', q = ['a', 'b'];
      eq(R.view(R.lensPath(p), R.set(R.lensPath(p), 11, R.set(R.lensPath(p), 10, testObj))), 11);
      eq(R.view(R.lensPath(q), R.set(R.lensPath(q), 11, R.set(R.lensPath(q), 10, testObj))), 11);
    });
  });
});
<commit_msg>Fix linting errors in lensPath test<commit_after>var R = require('..');
var eq = require('./shared/eq');

var testObj = {
  a: {
    b: 2
  },
  d: 3
};

describe('lensPath', function() {
  describe('view', function() {
    it('focuses the specified object property', function() {
      eq(R.view(R.lensPath(['d']), testObj), 3);
      eq(R.view(R.lensPath(['a', 'b']), testObj), 2);
      eq(R.view(R.lensPath([]), testObj), testObj);
    });
  });
  describe('set', function() {
    it('sets the value of the object property specified', function() {
      eq(R.set(R.lensPath(['d']), 0, testObj), {a: {b: 2}, d: 0});
      eq(R.set(R.lensPath(['a', 'b']), 0, testObj), {a: {b: 0}, d: 3});
      eq(R.set(R.lensPath([]), 0, testObj), 0);
    });
    it('adds the property to the object if it doesn\'t exist', function() {
      eq(R.set(R.lensPath('X'), 0, testObj), {a: {b: 2}, d: 3, X: 0});
      eq(R.set(R.lensPath(['a', 'X']), 0, testObj), {a: {b: 2, X: 0}, d: 3});
    });
  });
  describe('over', function() {
    it('applies function to the value of the specified object property', function() {
      eq(R.over(R.lensPath('d'), R.inc, testObj), {a: {b: 2}, d: 4});
      eq(R.over(R.lensPath(['a', 'b']), R.inc, testObj), {a: {b: 3}, d: 3});
      eq(R.over(R.lensPath([]), R.toPairs, testObj), [['a', {b: 2}], ['d', 3]]);
    });
    it('applies function to undefined and adds the property if it doesn\'t exist', function() {
      eq(R.over(R.lensPath(['X']), R.identity, testObj), {a: {b: 2}, d: 3, X: undefined});
      eq(R.over(R.lensPath(['a', 'X']), R.identity, testObj), {a: {b: 2, X: undefined}, d: 3});
    });
  });
  describe('composability', function() {
    it('can be composed', function() {
      var composedLens = R.compose(R.lensPath('a'), R.lensPath('b'));
      eq(R.view(composedLens, testObj), 2);
    });
  });
  describe('well behaved lens', function() {
    it('set s (get s) === s', function() {
      eq(R.set(R.lensPath('d'), R.view(R.lensPath('d'), testObj), testObj), testObj);
      eq(R.set(R.lensPath(['a', 'b']), R.view(R.lensPath(['a', 'b']), testObj), testObj), testObj);
    });
    it('get (set s v) === v', function() {
      eq(R.view(R.lensPath('d'), R.set(R.lensPath('d'), 0, testObj)), 0);
      eq(R.view(R.lensPath(['a', 'b']), R.set(R.lensPath(['a', 'b']), 0, testObj)), 0);
    });
    it('get (set(set s v1) v2) === v2', function() {
      var p = 'd';
      var q = ['a', 'b'];
      eq(R.view(R.lensPath(p), R.set(R.lensPath(p), 11, R.set(R.lensPath(p), 10, testObj))), 11);
      eq(R.view(R.lensPath(q), R.set(R.lensPath(q), 11, R.set(R.lensPath(q), 10, testObj))), 11);
    });
  });
});
<|endoftext|>


<commit_before>/**
* @class
*/
OpenLayers.Marker = Class.create();
OpenLayers.Marker.prototype = {

    /** @type OpenLayers.Icon */
    icon: null,

    /** location of object
    * @type OpenLayers.LonLat */
    lonlat: null,

    /** the data object associated with the marker
    * @type Object */
    data: null,

    /** @type OpenLayers.Events*/
    events: null,

    /** @type OpenLayers.Map */
    map: null,

    /** @type DOMElement */
    image: null,

    /**
    * @constructor
    *
    * @param {OpenLayers.Icon} icon
    * @param {OpenLayers.LonLat lonlat
    */
    initialize: function(lonlat, icon) {
        this.icon = icon;
        this.lonlat = lonlat;
        this.image = OpenLayers.Util.createImage(this.icon.url,
                                                 this.icon.size,
                                                 null,
                                                 "absolute"
                                                );
        this.events = new OpenLayers.Events(this, this.image, null);
    },

    /**
    * @param {OpenLayers.Pixel} px
    *
    * @return A new DOM Image with this markers icon set at the
    *         location passed-in
    * @type DOMElement
    */
    draw: function(px) {
        this.image.style.top = (px.y + this.icon.offset.y) + "px"
        this.image.style.left = (px.x + this.icon.offset.x) + "px";
        return this.image;
    },

    /**
    * @param {OpenLayers.Pixel} px
    */
    moveTo: function (px) {
        if ((px != null) && (this.div != null)) {
            this.image.style.top = (px.y + this.icon.offset.y) + "px"
            this.image.style.left = (px.x + this.icon.offset.x) + "px";
        }
    },

    /** @final @type String */
    CLASS_NAME: "OpenLayers.Marker"
}
<commit_msg>markers are no longer supposed to have associated data<commit_after>/**
* @class
*/
OpenLayers.Marker = Class.create();
OpenLayers.Marker.prototype = {

    /** @type OpenLayers.Icon */
    icon: null,

    /** location of object
    * @type OpenLayers.LonLat */
    lonlat: null,

    /** @type OpenLayers.Events*/
    events: null,

    /** @type OpenLayers.Map */
    map: null,

    /** @type DOMElement */
    image: null,

    /**
    * @constructor
    *
    * @param {OpenLayers.Icon} icon
    * @param {OpenLayers.LonLat lonlat
    */
    initialize: function(lonlat, icon) {
        this.icon = icon;
        this.lonlat = lonlat;
        this.image = OpenLayers.Util.createImage(this.icon.url,
                                                 this.icon.size,
                                                 null,
                                                 "absolute"
                                                );
        this.events = new OpenLayers.Events(this, this.image, null);
    },

    /**
    * @param {OpenLayers.Pixel} px
    *
    * @return A new DOM Image with this markers icon set at the
    *         location passed-in
    * @type DOMElement
    */
    draw: function(px) {
        this.image.style.top = (px.y + this.icon.offset.y) + "px"
        this.image.style.left = (px.x + this.icon.offset.x) + "px";
        return this.image;
    },

    /**
    * @param {OpenLayers.Pixel} px
    */
    moveTo: function (px) {
        if ((px != null) && (this.div != null)) {
            this.image.style.top = (px.y + this.icon.offset.y) + "px"
            this.image.style.left = (px.x + this.icon.offset.x) + "px";
        }
    },

    /** @final @type String */
    CLASS_NAME: "OpenLayers.Marker"
}
<|endoftext|>


<commit_before>'use strict';

var Chat      = require('../../index').Chat
  , ltx       = require('ltx')
  , helper    = require('../helper')
  , should    = require('should')
  , chatState = require('../../index').utils['xep-0085']

/* jshint -W030 */
describe('Chat', function() {

    var chat, socket, xmpp, manager

    before(function() {
        socket = new helper.SocketEventer()
        xmpp = new helper.XmppEventer()
        manager = {
            socket: socket,
            client: xmpp,
            jid: 'test@example.com',
            trackId: function(id, callback) {
                this.callback = callback
            },
            makeCallback: function(error, data) {
                this.callback(error, data)
            }
        }
        chat = new Chat()
        chat.init(manager)
    })

    beforeEach(function() {
        socket.removeAllListeners()
        xmpp.removeAllListeners()
        chat.init(manager)
    })

    describe('Can handle incoming messages', function() {

        it('Shouldn\'t handle non-message stanzas', function() {
            chat.handles(ltx.parse('<iq/>')).should.be.false
        })

        it('Should handle messages without a type', function() {
            chat.handles(ltx.parse('<message />')).should.be.true
        })

        it('Should confirm it can handle chat messages', function() {
            var item = ltx.parse('<message type="headline" />')
            chat.handles(item).should.be.false
        })

        it('Should handle chat type messages', function() {
            var item = ltx.parse('<message type="chat" />')
            chat.handles(item).should.be.true
        })

        it('Can handle simple plain text messages', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.from.should.eql({
                    user: 'user',
                    domain: 'domain',
                    resource: 'resource'
                })
                data.content.should.equal('message')
                data.format.should.equal(chat.PLAIN)
                done()
            })
            chat.handle(helper.getStanza('chat/plain')).should.be.true
        })

        it('Can handle XHTML type messages', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.from.should.eql({
                    user: 'user',
                    domain: 'domain',
                    resource: 'resource'
                })
                data.content
                    .should.equal('
Hello to you!
')
                data.format.should.equal(chat.XHTML)
                done()
            })
            chat.handle(helper.getStanza('chat/xhtml')).should.be.true
        })

        it('Can handle <delay> element', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.delay.when.should.equal('2002-09-10T23:08:25Z')
                data.delay.reason.should.equal('Offline Storage')
                data.delay.from.should.equal('capulet.com')
                done()
            })
            chat.handle(helper.getStanza('chat/plain-with-delay'))
                .should.be.true
        })

        it('Handles messages with a chat state notification', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.from.should.eql({
                    user: 'user',
                    domain: 'domain',
                    resource: 'resource'
                })
                data.content
                    .should.equal('
Hello to you!
')
                data.state.should.equal('composing')
                data.format.should.equal(chat.XHTML)
                done()
            })
            chat.handle(helper.getStanza('chat/xhtml-with-state')).should.be.true
        })

        it('Can handle just chat state notifications', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.from.should.eql({
                    user: 'user',
                    domain: 'domain',
                    resource: 'resource'
                })
                should.not.exist(data.content)
                should.not.exist(data.format)
                data.state.should.equal('composing')
                done()
            })
            chat.handle(helper.getStanza('chat/chat-state')).should.be.true
        })

        it('Can handle archived messages', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.archived.length.should.equal(1)
                data.archived[0].by.should.eql({
                    domain: 'shakespeare.lit',
                    user: 'juliet'
                })
                data.archived[0].id.should.equal('archive:1')
                done()
            })
            chat.handle(helper.getStanza('chat/chat-archived'))
                .should.be.true
        })

        it('https://github.com/lloydwatkin/xmpp-ftw/issues/40', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.should.eql({
                    from: { domain: 'buddycloud.org', user: 'lloyd', resource: '...' },
                    content: 'hey',
                    format: 'plain',
                    state: 'active'
                })
                done()
            })
            chat.handle(helper.getStanza('issues/40')).should.be.true
        })

    })

    describe('Can send messages', function() {

        it('Sends error message if \'to\' parameter missing', function(done) {
            socket.once('xmpp.error.client', function(data) {
                data.description.should.equal('Missing \'to\' key')
                data.type.should.equal('modify')
                data.condition.should.equal('client-error')
                data.request.should.eql({})
                done()
            })
            chat.sendMessage({})
        })

        it('Errors if \'content\' & chat state not provided', function(done) {
            socket.once('xmpp.error.client', function(data) {
                data.description
                    .should.equal('Message content or chat state not provided')
                data.type.should.equal('modify')
                data.condition.should.equal('client-error')
                data.request.to.should.equal('romeo@montague.net/orchard')
                data.request.type.should.equal('chat')
                done()
            })
            chat.sendMessage({ to: 'romeo@montague.net/orchard' })

        })

        it('Can send simple plain text messages', function(done) {
            var to = 'user@domain/resource'
            var content = 'message'
            xmpp.once('stanza', function(stanza) {
                stanza.attrs.to.should.equal(to)
                stanza.attrs.type.should.equal('chat')
                stanza.getChild('body').getText().should.equal(content)
                done()
            })
            chat.sendMessage({ to: to, content: content })
        })

        it('Returns error if invalid XHTML provided', function(done) {
            var to = 'romeo@montague.net/orchard'
            var content = 'This will fail'
            socket.once('xmpp.error.client', function(data) {
                data.description.should.equal('Can not parse XHTML message')
                data.type.should.equal('modify')
                data.condition.should.equal('client-error')
                data.request.to.should.equal(to)
                data.request.type.should.equal('chat'),
                data.request.content.should.equal(content)
                done()
            })
            chat.sendMessage({
                to: to,
                content: content,
                format: chat.XHTML
            })
        })

        it('Returns expected XHTML message stanza', function(done) {
            var to = 'romeo@montague.net/orchard'
            var content = '
This will pass
'
            xmpp.once('stanza', function(stanza) {
                stanza.getChild('body').getText()
                    .should.equal('This will pass')
                stanza.attrs.to.should.equal(to)
                stanza.getChild('html', 'http://jabber.org/protocol/xhtml-im')
                    .should.exist
                stanza.getChild('html')
                    .getChild('body', 'http://www.w3.org/1999/xhtml')
                    .should.exist
                stanza.getChild('html')
                    .getChild('body')
                    .children.join('')
                    .should.equal(content)
                done()
            })
            chat.sendMessage({
                to: to,
                content: content,
                format: chat.XHTML
            })
        })

        it('Should build stanza with chat state notification', function(done) {
            var to = 'romeo@montague.net/orchard'
            var content = '
This will pass
'
            xmpp.once('stanza', function(stanza) {
                stanza.getChild('body').getText()
                    .should.equal('This will pass')
                stanza.attrs.to.should.equal(to)
                stanza.getChild('html', 'http://jabber.org/protocol/xhtml-im')
                    .should.exist
                stanza.getChild('html')
                    .getChild('body', 'http://www.w3.org/1999/xhtml')
                    .should.exist
                stanza.getChild('html')
                    .getChild('body')
                    .children.join('')
                    .should.equal(content)
                done()
            })
            chat.sendMessage({
                to: to,
                content: content,
                format: chat.XHTML
            })
        })

        it('Should build stanza with just chat state', function(done) {
            var to = 'romeo@montague.net/orchard'
            var state = 'composing'
            xmpp.once('stanza', function(stanza) {
                stanza.attrs.to.should.equal(to)
                stanza.getChild('composing', chatState.NS).should.exist
                done()
            })
            chat.sendMessage({
                to: to,
                state: state
            })
        })

    })

    describe('Receipts XEP-0184', function() {

        describe('Incoming', function() {

        })

        describe('Outgoing', function() {

            it('Errors if receipt requested but no callback provided', function(done) {
                var request = {
                    to: 'user@example.com',
                    content: 'hello',
                    receipt: true
                }
                xmpp.once('stanza', function() {
                    done('Unexpected outgoing stanza')
                })
                socket.once('xmpp.error.client', function(error) {
                    error.type.should.equal('modify')
                    error.condition.should.equal('client-error')
                    error.description.should.equal('Callback required')
                    error.request.should.eql(request)
                    xmpp.removeAllListeners('stanza')
                    done()
                })
                socket.send('xmpp.chat.message', request)
            })

            it('Errors if non-function callback provided', function(done) {
                var request = {
                    to: 'user@example.com',
                    content: 'hello',
                    receipt: true
                }
                xmpp.once('stanza', function() {
                    done('Unexpected outgoing stanza')
                })
                socket.once('xmpp.error.client', function(error) {
                    error.type.should.equal('modify')
                    error.condition.should.equal('client-error')
                    error.description.should.equal('Missing callback')
                    error.request.should.eql(request)
                    xmpp.removeAllListeners('stanza')
                    done()
                })
                socket.send('xmpp.chat.message', request, true)
            })

            it('Sends expected stanza with receipt request', function(done) {
                var to = 'user@domain/resource'
                var content = 'message'
                xmpp.once('stanza', function(stanza) {
                    stanza.attrs.to.should.equal(to)
                    stanza.attrs.type.should.equal('chat')
                    stanza.getChild('body').getText().should.equal(content)
                    stanza.getChild('request', chat.NS_RECEIPT).should.exist
                    stanza.attrs.id.should.exist
                    done()
                })
                chat.sendMessage({ to: to, content: content, receipt: true }, function() {})
            })

            it('Retuns message ID', function(done) {
                var to = 'user@domain/resource'
                var content = 'message'
                var callback = function(error, success) {
                    should.not.exist(error)
                    success.id.should.exist
                    done()
                }
                chat.sendMessage({ to: to, content: content, receipt: true }, callback)
            })

        })

    })

})
<commit_msg>Returns message ID if valid callback provided<commit_after>'use strict';

var Chat      = require('../../index').Chat
  , ltx       = require('ltx')
  , helper    = require('../helper')
  , should    = require('should')
  , chatState = require('../../index').utils['xep-0085']

/* jshint -W030 */
describe('Chat', function() {

    var chat, socket, xmpp, manager

    before(function() {
        socket = new helper.SocketEventer()
        xmpp = new helper.XmppEventer()
        manager = {
            socket: socket,
            client: xmpp,
            jid: 'test@example.com',
            trackId: function(id, callback) {
                this.callback = callback
            },
            makeCallback: function(error, data) {
                this.callback(error, data)
            }
        }
        chat = new Chat()
        chat.init(manager)
    })

    beforeEach(function() {
        socket.removeAllListeners()
        xmpp.removeAllListeners()
        chat.init(manager)
    })

    describe('Can handle incoming messages', function() {

        it('Shouldn\'t handle non-message stanzas', function() {
            chat.handles(ltx.parse('<iq/>')).should.be.false
        })

        it('Should handle messages without a type', function() {
            chat.handles(ltx.parse('<message />')).should.be.true
        })

        it('Should confirm it can handle chat messages', function() {
            var item = ltx.parse('<message type="headline" />')
            chat.handles(item).should.be.false
        })

        it('Should handle chat type messages', function() {
            var item = ltx.parse('<message type="chat" />')
            chat.handles(item).should.be.true
        })

        it('Can handle simple plain text messages', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.from.should.eql({
                    user: 'user',
                    domain: 'domain',
                    resource: 'resource'
                })
                data.content.should.equal('message')
                data.format.should.equal(chat.PLAIN)
                done()
            })
            chat.handle(helper.getStanza('chat/plain')).should.be.true
        })

        it('Can handle XHTML type messages', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.from.should.eql({
                    user: 'user',
                    domain: 'domain',
                    resource: 'resource'
                })
                data.content
                    .should.equal('
Hello to you!
')
                data.format.should.equal(chat.XHTML)
                done()
            })
            chat.handle(helper.getStanza('chat/xhtml')).should.be.true
        })

        it('Can handle <delay> element', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.delay.when.should.equal('2002-09-10T23:08:25Z')
                data.delay.reason.should.equal('Offline Storage')
                data.delay.from.should.equal('capulet.com')
                done()
            })
            chat.handle(helper.getStanza('chat/plain-with-delay'))
                .should.be.true
        })

        it('Handles messages with a chat state notification', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.from.should.eql({
                    user: 'user',
                    domain: 'domain',
                    resource: 'resource'
                })
                data.content
                    .should.equal('
Hello to you!
')
                data.state.should.equal('composing')
                data.format.should.equal(chat.XHTML)
                done()
            })
            chat.handle(helper.getStanza('chat/xhtml-with-state')).should.be.true
        })

        it('Can handle just chat state notifications', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.from.should.eql({
                    user: 'user',
                    domain: 'domain',
                    resource: 'resource'
                })
                should.not.exist(data.content)
                should.not.exist(data.format)
                data.state.should.equal('composing')
                done()
            })
            chat.handle(helper.getStanza('chat/chat-state')).should.be.true
        })

        it('Can handle archived messages', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.archived.length.should.equal(1)
                data.archived[0].by.should.eql({
                    domain: 'shakespeare.lit',
                    user: 'juliet'
                })
                data.archived[0].id.should.equal('archive:1')
                done()
            })
            chat.handle(helper.getStanza('chat/chat-archived'))
                .should.be.true
        })

        it('https://github.com/lloydwatkin/xmpp-ftw/issues/40', function(done) {
            socket.once('xmpp.chat.message', function(data) {
                data.should.eql({
                    from: { domain: 'buddycloud.org', user: 'lloyd', resource: '...' },
                    content: 'hey',
                    format: 'plain',
                    state: 'active'
                })
                done()
            })
            chat.handle(helper.getStanza('issues/40')).should.be.true
        })

    })

    describe('Can send messages', function() {

        it('Sends error message if \'to\' parameter missing', function(done) {
            socket.once('xmpp.error.client', function(data) {
                data.description.should.equal('Missing \'to\' key')
                data.type.should.equal('modify')
                data.condition.should.equal('client-error')
                data.request.should.eql({})
                done()
            })
            chat.sendMessage({})
        })

        it('Errors if \'content\' & chat state not provided', function(done) {
            socket.once('xmpp.error.client', function(data) {
                data.description
                    .should.equal('Message content or chat state not provided')
                data.type.should.equal('modify')
                data.condition.should.equal('client-error')
                data.request.to.should.equal('romeo@montague.net/orchard')
                data.request.type.should.equal('chat')
                done()
            })
            chat.sendMessage({ to: 'romeo@montague.net/orchard' })

        })

        it('Can send simple plain text messages', function(done) {
            var to = 'user@domain/resource'
            var content = 'message'
            xmpp.once('stanza', function(stanza) {
                stanza.attrs.to.should.equal(to)
                stanza.attrs.type.should.equal('chat')
                stanza.getChild('body').getText().should.equal(content)
                done()
            })
            chat.sendMessage({ to: to, content: content })
        })

        it('Returns error if invalid XHTML provided', function(done) {
            var to = 'romeo@montague.net/orchard'
            var content = 'This will fail'
            socket.once('xmpp.error.client', function(data) {
                data.description.should.equal('Can not parse XHTML message')
                data.type.should.equal('modify')
                data.condition.should.equal('client-error')
                data.request.to.should.equal(to)
                data.request.type.should.equal('chat'),
                data.request.content.should.equal(content)
                done()
            })
            chat.sendMessage({
                to: to,
                content: content,
                format: chat.XHTML
            })
        })

        it('Returns expected XHTML message stanza', function(done) {
            var to = 'romeo@montague.net/orchard'
            var content = '
This will pass
'
            xmpp.once('stanza', function(stanza) {
                stanza.getChild('body').getText()
                    .should.equal('This will pass')
                stanza.attrs.to.should.equal(to)
                stanza.getChild('html', 'http://jabber.org/protocol/xhtml-im')
                    .should.exist
                stanza.getChild('html')
                    .getChild('body', 'http://www.w3.org/1999/xhtml')
                    .should.exist
                stanza.getChild('html')
                    .getChild('body')
                    .children.join('')
                    .should.equal(content)
                done()
            })
            chat.sendMessage({
                to: to,
                content: content,
                format: chat.XHTML
            })
        })

        it('Should build stanza with chat state notification', function(done) {
            var to = 'romeo@montague.net/orchard'
            var content = '
This will pass
'
            xmpp.once('stanza', function(stanza) {
                stanza.getChild('body').getText()
                    .should.equal('This will pass')
                stanza.attrs.to.should.equal(to)
                stanza.getChild('html', 'http://jabber.org/protocol/xhtml-im')
                    .should.exist
                stanza.getChild('html')
                    .getChild('body', 'http://www.w3.org/1999/xhtml')
                    .should.exist
                stanza.getChild('html')
                    .getChild('body')
                    .children.join('')
                    .should.equal(content)
                done()
            })
            chat.sendMessage({
                to: to,
                content: content,
                format: chat.XHTML
            })
        })

        it('Should build stanza with just chat state', function(done) {
            var to = 'romeo@montague.net/orchard'
            var state = 'composing'
            xmpp.once('stanza', function(stanza) {
                stanza.attrs.to.should.equal(to)
                stanza.getChild('composing', chatState.NS).should.exist
                done()
            })
            chat.sendMessage({
                to: to,
                state: state
            })
        })

    })

    it('Returns message ID if callback provided', function(done) {
            var request = {
                to: 'user@example.com',
                content: 'hello'
            }
            socket.send('xmpp.chat.message', request, function(error, data) {
                data.id.should.exist
                should.not.exist(error)
                done()
            })
        })

    describe('Receipts XEP-0184', function() {

        describe('Incoming', function() {

        })

        describe('Outgoing', function() {

            it('Errors if receipt requested but no callback provided', function(done) {
                var request = {
                    to: 'user@example.com',
                    content: 'hello',
                    receipt: true
                }
                xmpp.once('stanza', function() {
                    done('Unexpected outgoing stanza')
                })
                socket.once('xmpp.error.client', function(error) {
                    error.type.should.equal('modify')
                    error.condition.should.equal('client-error')
                    error.description.should.equal('Callback required')
                    error.request.should.eql(request)
                    xmpp.removeAllListeners('stanza')
                    done()
                })
                socket.send('xmpp.chat.message', request)
            })

            it('Errors if non-function callback provided', function(done) {
                var request = {
                    to: 'user@example.com',
                    content: 'hello',
                    receipt: true
                }
                xmpp.once('stanza', function() {
                    done('Unexpected outgoing stanza')
                })
                socket.once('xmpp.error.client', function(error) {
                    error.type.should.equal('modify')
                    error.condition.should.equal('client-error')
                    error.description.should.equal('Missing callback')
                    error.request.should.eql(request)
                    xmpp.removeAllListeners('stanza')
                    done()
                })
                socket.send('xmpp.chat.message', request, true)
            })

            it('Sends expected stanza with receipt request', function(done) {
                var to = 'user@domain/resource'
                var content = 'message'
                xmpp.once('stanza', function(stanza) {
                    stanza.attrs.to.should.equal(to)
                    stanza.attrs.type.should.equal('chat')
                    stanza.getChild('body').getText().should.equal(content)
                    stanza.getChild('request', chat.NS_RECEIPT).should.exist
                    stanza.attrs.id.should.exist
                    done()
                })
                chat.sendMessage({ to: to, content: content, receipt: true }, function() {})
            })

            it('Retuns message ID', function(done) {
                var to = 'user@domain/resource'
                var content = 'message'
                var callback = function(error, success) {
                    should.not.exist(error)
                    success.id.should.exist
                    done()
                }
                chat.sendMessage({ to: to, content: content, receipt: true }, callback)
            })

        })

    })

})
<|endoftext|>


<commit_before>'use strict';

var types = require('../../lib/types');

var sinon = require('sinon');

var path = require('path');

var data = {
  result: Object(),
  this: Object(),
  absolutePath: path.resolve(__filename),
  relativePath: path.relative(process.cwd(), __filename),
  ordinary: {
    fd: 1,
    // Fool the naive string-sniffing approach.
    buffer: path.resolve(__filename),
    number: 14,
    mode: 0o444,
    flags: 'r+',
    uid: 512,
    symlinkType: 'file',
    timestamp: '123456789',
    options: { encoding: 'utf8' },
    callback: sinon.stub().throws()
  }
};

exports.result = data.result;
exports.this = data.this;

var defaultArg = function (type) {
  if (type.typeName in data.ordinary) {
    return data.ordinary[type.typeName];
  }
  throw Error('Invalid type: ' + (type ? type.typeName : undefined));
};

exports.inputArgs = function (argTypes) {
  return argTypes.map(function (type) {
    return (type === types.path) ? data.absolutePath : defaultArg(type);
  });
};

exports.outputArgs = function (argTypes) {
  return argTypes.map(function (type) {
    return (type === types.path) ? data.relativePath : defaultArg(type);
  });
};
<commit_msg>test/lib/data: don't use octal literals<commit_after>'use strict';

var types = require('../../lib/types');

var sinon = require('sinon');

var path = require('path');

var data = {
  result: Object(),
  this: Object(),
  absolutePath: path.resolve(__filename),
  relativePath: path.relative(process.cwd(), __filename),
  ordinary: {
    fd: 1,
    // Fool the naive string-sniffing approach.
    buffer: path.resolve(__filename),
    number: 14,
    mode: Number.parseInt('444', 8),
    flags: 'r+',
    uid: 512,
    symlinkType: 'file',
    timestamp: '123456789',
    options: { encoding: 'utf8' },
    callback: sinon.stub().throws()
  }
};

exports.result = data.result;
exports.this = data.this;

var defaultArg = function (type) {
  if (type.typeName in data.ordinary) {
    return data.ordinary[type.typeName];
  }
  throw Error('Invalid type: ' + (type ? type.typeName : undefined));
};

exports.inputArgs = function (argTypes) {
  return argTypes.map(function (type) {
    return (type === types.path) ? data.absolutePath : defaultArg(type);
  });
};

exports.outputArgs = function (argTypes) {
  return argTypes.map(function (type) {
    return (type === types.path) ? data.relativePath : defaultArg(type);
  });
};
<|endoftext|>


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

var express = require('express'),
  bodyParser = require('body-parser'),
  request = require('supertest'),
  should = require('should');

var oauth2server = require('../');

var bootstrap = function (oauthConfig) {
  var app = express();
  app.oauth = oauth2server(oauthConfig || {
      model: {}
    });

  app.use(bodyParser());

  app.all('/oauth/token', app.oauth.grant);

  app.all('/private', function (req, res, next) {
    res.send('Hello');
  });

  app.all('/public', app.oauth.bypass, function (req, res, next) {
    res.send('Hello');
  });

  app.oauth.lockdown(app);

  app.use(app.oauth.errorHandler());

  return app;
};

describe('Lockdown pattern', function() {

  it('should substitute grant', function (done) {
    var app = bootstrap();

    request(app)
      .get('/oauth/token')
      .expect(400, /method must be POST/i, done);
  });

  it('should insert authorise by default', function (done) {
    var app = bootstrap();

    request(app)
      .get('/private')
      .expect(400, /access token was not found/i, done);
  });

  it('should pass valid request through authorise', function (done) {
    var app = bootstrap({
      model: {
        getAccessToken: function (token, callback) {
          callback(token !== 'thom', { access_token: token, expires: null });
        }
      }
    });

    request(app)
      .get('/private?access_token=thom')
      .expect(200, /hello/i, done);
  });

  it('should correctly bypass', function (done) {
    var app = bootstrap();

    request(app)
      .get('/public')
      .expect(200, /hello/i, done);
  });

  describe('in express 3', function () {
    var app, privateAction, publicAction;

    beforeEach(function () {
      privateAction = function () {};
      publicAction = function () {};

      // mock express 3 app
      app = {
        routes: {
          get: [
            { callbacks: [ privateAction ] }
          ]
        }
      };

      app.oauth = oauth2server({ model: {} });
      app.routes.get.push({ callbacks: [ app.oauth.bypass, publicAction ] })
      app.oauth.lockdown(app);
    });

    it('adds authorise to non-bypassed routes', function () {
      app.routes.get[0].callbacks[1].should.equal(privateAction);
    });

    it('removes oauth.bypass from bypassed routes', function () {
      app.routes.get[1].callbacks[0].should.equal(publicAction);
    });
  });
});
<commit_msg>Cleaner test style<commit_after>/**
 * Copyright 2013-present NightWorld.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var express = require('express'),
  bodyParser = require('body-parser'),
  request = require('supertest'),
  should = require('should');

var oauth2server = require('../');

var bootstrap = function (oauthConfig) {
  var app = express();
  app.oauth = oauth2server(oauthConfig || {
      model: {}
    });

  app.use(bodyParser());

  app.all('/oauth/token', app.oauth.grant);

  app.all('/private', function (req, res, next) {
    res.send('Hello');
  });

  app.all('/public', app.oauth.bypass, function (req, res, next) {
    res.send('Hello');
  });

  app.oauth.lockdown(app);

  app.use(app.oauth.errorHandler());

  return app;
};

describe('Lockdown pattern', function() {

  it('should substitute grant', function (done) {
    var app = bootstrap();

    request(app)
      .get('/oauth/token')
      .expect(400, /method must be POST/i, done);
  });

  it('should insert authorise by default', function (done) {
    var app = bootstrap();

    request(app)
      .get('/private')
      .expect(400, /access token was not found/i, done);
  });

  it('should pass valid request through authorise', function (done) {
    var app = bootstrap({
      model: {
        getAccessToken: function (token, callback) {
          callback(token !== 'thom', { access_token: token, expires: null });
        }
      }
    });

    request(app)
      .get('/private?access_token=thom')
      .expect(200, /hello/i, done);
  });

  it('should correctly bypass', function (done) {
    var app = bootstrap();

    request(app)
      .get('/public')
      .expect(200, /hello/i, done);
  });

  describe('in express 3', function () {
    var app, privateAction, publicAction;

    beforeEach(function () {
      privateAction = function () {};
      publicAction = function () {};

      // mock express 3 app
      app = {
        routes: { get: [] }
      };

      app.oauth = oauth2server({ model: {} });
      app.routes.get.push({ callbacks: [ privateAction ] });
      app.routes.get.push({ callbacks: [ app.oauth.bypass, publicAction ] })
      app.oauth.lockdown(app);
    });

    it('adds authorise to non-bypassed routes', function () {
      app.routes.get[0].callbacks[1].should.equal(privateAction);
    });

    it('removes oauth.bypass from bypassed routes', function () {
      app.routes.get[1].callbacks[0].should.equal(publicAction);
    });
  });
});
<|endoftext|>


<commit_before>if (typeof module !== "undefined") {
    var Polynomial = require('kld-polynomial').Polynomial,
        SqrtPolynomial = require('kld-polynomial').SqrtPolynomial,
        affine = require('kld-affine'),
        Matrix2D = affine.Matrix2D,
        Point2D = affine.Point2D,
        Rectangle2D = require('./Rectangle2D');
}

/**
 *  QuadraticBezier2D
 *
 *  @param {Point2D} p1
 *  @param {Point2D} p2
 *  @param {Point2D} p3
 *  @returns {QuadraticBezier2D}
 */
function QuadraticBezier2D() {
    Object.defineProperties(this, {
        "p1": {
            value: p1,
            writable: false,
            enumerable: true,
            configurable: false
        },
        "p2": {
            value: p2,
            writable: false,
            enumerable: true,
            configurable: false
        },
        "p3": {
            value: p3,
            writable: false,
            enumerable: true,
            configurable: false
        }
    });
    // this.p1 = p1;
    // this.p2 = p2;
    // this.p3 = p3;
}

/**
 *  getPointAtParameter
 *
 *  @param {Number} t
 *  @eturns {Point2D}
 */
QuadraticBezier2D.prototype.getPointAtParameter = function(t) {
    // TODO: validate t in [0,1]

    // first round of lerps
    var p4 = this.p1.lerp(this.p2, t);
    var p5 = this.p2.lerp(this.p3, t);

    return p4.lerp(p5, t);
};

/**
 *  splitAtParameter
 *
 *  @param {Number} t
 *  @returns {Array<QuadraticBezier2D>}
 */
QuadraticBezier2D.prototype.splitAtParameter = function(t) {
    // first round of lerps
    var p4 = this.p1.lerp(this.p2, t);
    var p5 = this.p2.lerp(this.p3, t);

    // second round of lerps
    var p6 = p4.lerp(p5, t);

    return [
        new QuadraticBezier2D(this.p1, p4, p6),
        new QuadraticBezier2D(p6, p5, this.p3)
    ];
};

/**
 *  getBernsteinPolynomials
 *
 *  @returns {x: Polynomial, y: Polynomial}
 */
QuadraticBezier2D.prototype.getBernsteinPolynomials = function() {
    var a, b;             // temporary variables
    var c2, c1, c0;       // coefficients of quadratic

    a = this.p2.multiply(-2);
    c2 = this.p1.add(a.add(this.p3));

    a = this.p1.multiply(-2);
    b = this.p2.multiply(2);
    c1 = a.add(b);

    c0 = this.p1;

    return {
        x: new Polynomial(c2.x, c1.x, c0.x),
        y: new Polynomial(c2.y, c1.y, c0.y)
    };
};

/**
 *  getArcLengthPolynomial
 *
 *  @returns {SqrtPolynomial}
 */
QuadraticBezier2D.prototype.getArcLengthPolynomial = function() {
    if (!this.hasOwnProperty("arcLengthPolynomial")) {
        var a, b;
        var c1, c2;

        a = this.p2.multiply(-2);
        c2 = this.p1.add(a.add(this.p3));

        a = this.p1.multiply(-2);
        b = this.p2.multiply(2);
        c1 = a.add(b);

        // c1x + c1y + (2 c2x + 2 c2y) t
        //  ____________
        // √ dx^2 + dy^2
        //
        this.arcLengthPolynomial = new SqrtPolynomial(
             2 * (c2.x + c2.y),
                  c1.x + c1.y
        );

        // this.arcLength = this.arcLengthPolynomial.romberg(0, 1);
        this.arcLength = this.arcLengthPolynomial.simpson(0, 1);
    }

    return this.arcLengthPolynomial;
};

/**
 *  getParameterFromArcLength
 *
 *  @param {Number} length
 *  @returns {Number}
 */
CubicBezier2D.prototype.getParameterFromArcLength = function(length) {
    // TODO: extract common Bezier code

    // make sure the arc length polynomial and arc length values have been calculated
    var arcLengthPolynomial = this.getArcLengthPolynomial();
    var result;

    if (length <= 0) {
        result = 0;
    }
    else if (length >= this.arcLength) {
        result = 1;
    }
    else {
        var TOLERANCE = 1e-9;
        var MAXITERS = 20;

        result = length / this.arcLength;

        for ( var i = 0; i <= MAXITERS; i++ ) {
            var diff = arcLengthPolynomial.romberg(0, result) - length;
            //var diff = arcLengthPolynomial.simpson(0, result) - s;

            if ( Math.abs(diff) < TOLERANCE ) {
                break;
            }

            var value = arcLengthPolynomial.eval(result);

            if ( value == 0 ) {
                break;
            }

            result -= diff / value;
        }
    }

    return result;
};

/**
 *  getBoundingBox
 *
 *  @returns {Rectangle2D}
 */
QuadraticBezier2D.prototype.getBoundingBox = function() {
    var polys = this.getBernsteinPolynomials();
    var dx = polys.x.getDerivative();
    var dy = polys.y.getDerivative();
    var roots = dx.getRootsInInterval(0, 1);
    roots = roots.concat(dy.getRootsInInterval(0, 1));
    // var roots = dx.getRoots();
    // roots = roots.concat(dy.getRoots());

    var min = this.p1.min(this.p3);
    var max = this.p1.max(this.p3);

    roots.forEach(function(t) {
        if (0 <= t && t <= 1) {
            var testPoint = new Point2D(
                polys.x.eval(t),
                polys.y.eval(t)
            );

            min = min.min(testPoint);
            max = max.max(testPoint);
        }
    });

    return new Rectangle2D(
        min.x,
        min.y,
        max.x - min.x,
        max.y - min.y
    );
};

/**
 *  getAlignedBoundingBox
 *
 *  @returns { bbox: Rectangle2D, transform: Matrix2D }
 */
QuadraticBezier2D.prototype.getAlignedBoundingBox = function() {
    return {
        bbox: this.getAlignedBezier().getBoundingBox(),
        transform: new Matrix2D()
            .translate(this.p1.x, this.p1.y)
            .rotateFromVector(Vector2D.fromPoints(this.p1, this.p3))
    };
};

/**
 *  getAlignedBezier
 *
 *  @returns {QuadraticBezier2D}
 */
QuadraticBezier2D.prototype.getAlignedBezier = function() {
    var matrix = new Matrix2D();

    // move p1 to the origin
    matrix = matrix.translate(this.p1.x, this.p1.y);

    // rotate vector from p1 to p4 to x-axis
    matrix = matrix.rotateFromVector(Vector2D.fromPoints(this.p1, this.p3));

    // reverse transforms
    matrix = matrix.inverse();

    // apply to each point and create new Bezier
    return new QuadraticBezier2D(
        this.p1.transform(matrix),
        this.p2.transform(matrix),
        this.p3.transform(matrix)
    );
};

/**
 *  tesselate
 *
 *  @returns {Array<Point2D>}
 */
QuadraticBezier2D.prototype.tesselate = function() {

};

/**
 *  toString
 *
 *  @returns {String}
 */
QuadraticBezier2D.prototype.toString = function() {
    return (
        "M" + this.p1.x + "," + this.p1.y + " " +
        "Q" + this.p2.x + "," + this.p2.y +
        " " + this.p3.x + "," + this.p3.y
    );
};

if (typeof module !== "undefined") {
    module.exports = QuadraticBezier2D;
}
<commit_msg>Fix polynomial for quadratic bezier arc length<commit_after>if (typeof module !== "undefined") {
    var Polynomial = require('kld-polynomial').Polynomial,
        SqrtPolynomial = require('kld-polynomial').SqrtPolynomial,
        affine = require('kld-affine'),
        Matrix2D = affine.Matrix2D,
        Point2D = affine.Point2D,
        Rectangle2D = require('./Rectangle2D');
}

/**
 *  QuadraticBezier2D
 *
 *  @param {Point2D} p1
 *  @param {Point2D} p2
 *  @param {Point2D} p3
 *  @returns {QuadraticBezier2D}
 */
function QuadraticBezier2D() {
    Object.defineProperties(this, {
        "p1": {
            value: p1,
            writable: false,
            enumerable: true,
            configurable: false
        },
        "p2": {
            value: p2,
            writable: false,
            enumerable: true,
            configurable: false
        },
        "p3": {
            value: p3,
            writable: false,
            enumerable: true,
            configurable: false
        }
    });
    // this.p1 = p1;
    // this.p2 = p2;
    // this.p3 = p3;
}

/**
 *  getPointAtParameter
 *
 *  @param {Number} t
 *  @eturns {Point2D}
 */
QuadraticBezier2D.prototype.getPointAtParameter = function(t) {
    // TODO: validate t in [0,1]

    // first round of lerps
    var p4 = this.p1.lerp(this.p2, t);
    var p5 = this.p2.lerp(this.p3, t);

    return p4.lerp(p5, t);
};

/**
 *  splitAtParameter
 *
 *  @param {Number} t
 *  @returns {Array<QuadraticBezier2D>}
 */
QuadraticBezier2D.prototype.splitAtParameter = function(t) {
    // first round of lerps
    var p4 = this.p1.lerp(this.p2, t);
    var p5 = this.p2.lerp(this.p3, t);

    // second round of lerps
    var p6 = p4.lerp(p5, t);

    return [
        new QuadraticBezier2D(this.p1, p4, p6),
        new QuadraticBezier2D(p6, p5, this.p3)
    ];
};

/**
 *  getBernsteinPolynomials
 *
 *  @returns {x: Polynomial, y: Polynomial}
 */
QuadraticBezier2D.prototype.getBernsteinPolynomials = function() {
    var a, b;             // temporary variables
    var c2, c1, c0;       // coefficients of quadratic

    a = this.p2.multiply(-2);
    c2 = this.p1.add(a.add(this.p3));

    a = this.p1.multiply(-2);
    b = this.p2.multiply(2);
    c1 = a.add(b);

    c0 = this.p1;

    return {
        x: new Polynomial(c2.x, c1.x, c0.x),
        y: new Polynomial(c2.y, c1.y, c0.y)
    };
};

/**
 *  getArcLengthPolynomial
 *
 *  @returns {SqrtPolynomial}
 */
QuadraticBezier2D.prototype.getArcLengthPolynomial = function() {
    if (!this.hasOwnProperty("arcLengthPolynomial")) {
        var a, b;
        var c1, c2;

        a = this.p2.multiply(-2);
        c2 = this.p1.add(a.add(this.p3));

        a = this.p1.multiply(-2);
        b = this.p2.multiply(2);
        c1 = a.add(b);

        //  ____________
        // √ dx^2 + dy^2
        //
        this.arcLengthPolynomial = new SqrtPolynomial(
            4 * (c2.x*c2.x + c2.y*c2.y),
            4 * (c1.x*c2.x + c1.y*c2.y),
                 c1.x*c1.x + c1.y*c1.y
        );

        // this.arcLength = this.arcLengthPolynomial.romberg(0, 1);
        this.arcLength = this.arcLengthPolynomial.simpson(0, 1);
    }

    return this.arcLengthPolynomial;
};

/**
 *  getParameterFromArcLength
 *
 *  @param {Number} length
 *  @returns {Number}
 */
CubicBezier2D.prototype.getParameterFromArcLength = function(length) {
    // TODO: extract common Bezier code

    // make sure the arc length polynomial and arc length values have been calculated
    var arcLengthPolynomial = this.getArcLengthPolynomial();
    var result;

    if (length <= 0) {
        result = 0;
    }
    else if (length >= this.arcLength) {
        result = 1;
    }
    else {
        var TOLERANCE = 1e-9;
        var MAXITERS = 20;

        result = length / this.arcLength;

        for ( var i = 0; i <= MAXITERS; i++ ) {
            var diff = arcLengthPolynomial.romberg(0, result) - length;
            //var diff = arcLengthPolynomial.simpson(0, result) - s;

            if ( Math.abs(diff) < TOLERANCE ) {
                break;
            }

            var value = arcLengthPolynomial.eval(result);

            if ( value == 0 ) {
                break;
            }

            result -= diff / value;
        }
    }

    return result;
};

/**
 *  getBoundingBox
 *
 *  @returns {Rectangle2D}
 */
QuadraticBezier2D.prototype.getBoundingBox = function() {
    var polys = this.getBernsteinPolynomials();
    var dx = polys.x.getDerivative();
    var dy = polys.y.getDerivative();
    var roots = dx.getRootsInInterval(0, 1);
    roots = roots.concat(dy.getRootsInInterval(0, 1));
    // var roots = dx.getRoots();
    // roots = roots.concat(dy.getRoots());

    var min = this.p1.min(this.p3);
    var max = this.p1.max(this.p3);

    roots.forEach(function(t) {
        if (0 <= t && t <= 1) {
            var testPoint = new Point2D(
                polys.x.eval(t),
                polys.y.eval(t)
            );

            min = min.min(testPoint);
            max = max.max(testPoint);
        }
    });

    return new Rectangle2D(
        min.x,
        min.y,
        max.x - min.x,
        max.y - min.y
    );
};

/**
 *  getAlignedBoundingBox
 *
 *  @returns { bbox: Rectangle2D, transform: Matrix2D }
 */
QuadraticBezier2D.prototype.getAlignedBoundingBox = function() {
    return {
        bbox: this.getAlignedBezier().getBoundingBox(),
        transform: new Matrix2D()
            .translate(this.p1.x, this.p1.y)
            .rotateFromVector(Vector2D.fromPoints(this.p1, this.p3))
    };
};

/**
 *  getAlignedBezier
 *
 *  @returns {QuadraticBezier2D}
 */
QuadraticBezier2D.prototype.getAlignedBezier = function() {
    var matrix = new Matrix2D();

    // move p1 to the origin
    matrix = matrix.translate(this.p1.x, this.p1.y);

    // rotate vector from p1 to p4 to x-axis
    matrix = matrix.rotateFromVector(Vector2D.fromPoints(this.p1, this.p3));

    // reverse transforms
    matrix = matrix.inverse();

    // apply to each point and create new Bezier
    return new QuadraticBezier2D(
        this.p1.transform(matrix),
        this.p2.transform(matrix),
        this.p3.transform(matrix)
    );
};

/**
 *  tesselate
 *
 *  @returns {Array<Point2D>}
 */
QuadraticBezier2D.prototype.tesselate = function() {

};

/**
 *  toString
 *
 *  @returns {String}
 */
QuadraticBezier2D.prototype.toString = function() {
    return (
        "M" + this.p1.x + "," + this.p1.y + " " +
        "Q" + this.p2.x + "," + this.p2.y +
        " " + this.p3.x + "," + this.p3.y
    );
};

if (typeof module !== "undefined") {
    module.exports = QuadraticBezier2D;
}
<|endoftext|>