<commit_before>
describe("A number field", function() {
    var field = document.createElement("input"),
        v = fieldValidator.validate;

    field.setAttribute("type", "number");
    field.setAttribute("step", "any");

    document.body.appendChild(field);

    it("should flag \"min\" errors", function() {
        field.setAttribute("min", "6");
        field.value = "5";
        expect(v(field)).toEqual([{field: field, errors: ["min"], isValid: false}]);

        field.value = "6";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "7";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.setAttribute("min", "0.01");
        field.value = "0.01";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "0.005";
        expect(v(field)).toEqual([{field: field, errors: ["min"], isValid: false}]);

        field.value = "1";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);
    });

    it("should flag \"max\" errors", function() {
        field.setAttribute("max", "0.1");
        field.value = "0.05";

        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "0.2";
        expect(v(field)).toEqual([{field: field, errors: ["max"], isValid: false}]);

        field.setAttribute("max", "10");
        field.value = "11";
        expect(v(field)).toEqual([{field: field, errors: ["max"], isValid: false}]);

        field.value = "10";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);
    });

    it("should flag \"step\" errors", function() {
        field.setAttribute("step", "2");
        field.removeAttribute("min");
        field.removeAttribute("max");

        field.value = "1";
        expect(v(field)).toEqual([{field: field, errors: ["step"], isValid: false}]);

        field.value = "3";
        expect(v(field)).toEqual([{field: field, errors: ["step"], isValid: false}]);

        field.value = "2";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "4";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.setAttribute("step", "0.001");

        field.value = "0.004";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "0.5";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "0.0003";
        expect(v(field)).toEqual([{field: field, errors: ["step"], isValid: false}]);
    });

    it("should flag \"required\" errors", function() {
        field.setAttribute("required", "required");

        field.value = "";
        expect(v(field)).toEqual([{field: field, errors: ["required"], isValid: false}]);

        field.value = "7";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);
    });

    it("should not flag errors for invalid numeric-type validation attributes", function() {
        field.setAttribute("minlength", "6");
        field.setAttribute("maxlength", "10");
        field.setAttribute("pattern", "^[a-zA-Z]$");

        field.value = "9";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);
    });
});
<commit_msg>added tests for step="any"<commit_after>
describe("A number field", function() {
    var field = document.createElement("input"),
        v = fieldValidator.validate;

    field.setAttribute("type", "number");
    field.setAttribute("step", "any");

    document.body.appendChild(field);

    it("should flag \"min\" errors", function() {
        field.setAttribute("min", "6");
        field.value = "5";
        expect(v(field)).toEqual([{field: field, errors: ["min"], isValid: false}]);

        field.value = "6";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "7";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.setAttribute("min", "0.01");
        field.value = "0.01";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "0.005";
        expect(v(field)).toEqual([{field: field, errors: ["min"], isValid: false}]);

        field.value = "1";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);
    });

    it("should flag \"max\" errors", function() {
        field.setAttribute("max", "0.1");
        field.value = "0.05";

        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "0.2";
        expect(v(field)).toEqual([{field: field, errors: ["max"], isValid: false}]);

        field.setAttribute("max", "10");
        field.value = "11";
        expect(v(field)).toEqual([{field: field, errors: ["max"], isValid: false}]);

        field.value = "10";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);
    });

    it("should flag \"step\" errors", function() {
        field.setAttribute("step", "2");
        field.removeAttribute("min");
        field.removeAttribute("max");

        field.value = "1";
        expect(v(field)).toEqual([{field: field, errors: ["step"], isValid: false}]);

        field.value = "3";
        expect(v(field)).toEqual([{field: field, errors: ["step"], isValid: false}]);

        field.value = "2";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "4";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.setAttribute("step", "0.001");

        field.value = "0.004";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "0.5";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "0.0003";
        expect(v(field)).toEqual([{field: field, errors: ["step"], isValid: false}]);

        // should accept step "any"
        field.setAttribute("step", "any");
        field.value = "0.004";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "0.5";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "0.0003";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "1";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "3";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "2";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

        field.value = "4";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);

    });

    it("should flag \"required\" errors", function() {
        field.setAttribute("required", "required");

        field.value = "";
        expect(v(field)).toEqual([{field: field, errors: ["required"], isValid: false}]);

        field.value = "7";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);
    });

    it("should not flag errors for invalid numeric-type validation attributes", function() {
        field.setAttribute("minlength", "6");
        field.setAttribute("maxlength", "10");
        field.setAttribute("pattern", "^[a-zA-Z]$");

        field.value = "9";
        expect(v(field)).toEqual([{field: field, errors: [], isValid: true}]);
    });
});
<|endoftext|>


<commit_before>require("../js/players/players.js");
require("../js/sequencing/sequencing.js");
require("../js/progression/progression.js");
require("../js/theory/theory.js");
require("../js/mn-scale.js");

var assert = require("assert");

function testSequenceRendering(baseSequence, progression, expected)
{
  var signature = new Signature;
  var ticksPerBeat = kTicksPerBeats;

  // Build the basic chord structure

  var chords = makeChordProgression(progression.root, progression.scale, progression.degrees);

  var harmonicStructure = createTimeline(chords, createSequencingPosition(ticksPerBeat * signature.denominator, ticksPerBeat));
  var length = createSequencingPosition(chords.length * ticksPerBeat * signature.denominator, ticksPerBeat);
  harmonicStructure.setLength(length);
  // render the combination

  var rendered = renderSequence(harmonicStructure, baseSequence, signature, ticksPerBeat);

  // Test against expected

  expected.length = convertToPosition(expected.length, signature, ticksPerBeat)
  expected.sequence.forEach(function(element)
  {
    element.position = convertToPosition(element.position, signature, ticksPerBeat)
  });
  assert.deepEqual(rendered, expected);
}

//==============================================================================

var baseSequence = {
    length : "1.4.1",
    sequence:
      [
        { position: "1.1.1", degrees: [{d:1, t:-12}, 1,2]},
        { position: "1.2.1", degrees: [2]},
        { position: "1.3.1", degrees: [3,1]},
      ]
    }

var progression = {
    root: "c3",
    scale: "major",
    degrees: [1,5]
}

var expected = {
  length: "3.1.1",
  sequence:
    [
      { position: "1.1.1", notes: [36, 48, 52]},
      { position: "1.2.1", notes: [52]},
      { position: "1.3.1", notes: [55, 48]},
      { position: "1.4.1", notes: [36, 48, 52]},
      { position: "2.1.1", notes: [43, 55, 59]},
      { position: "2.2.1", notes: [59]},
      { position: "2.3.1", notes: [62, 55]},
      { position: "2.4.1", notes: [43, 55, 59]},
    ]
}

testSequenceRendering(baseSequence, progression, expected);
<commit_msg>Add test for non 4/4 timesignature<commit_after>require("../js/players/players.js");
require("../js/sequencing/sequencing.js");
require("../js/progression/progression.js");
require("../js/theory/theory.js");
require("../js/mn-scale.js");

var assert = require("assert");

function testSequenceRendering(signature, baseSequence, progression, expected)
{
  var ticksPerBeat = kTicksPerBeats;

  // Build the basic chord structure

  var chords = makeChordProgression(progression.root, progression.scale, progression.degrees);

  var harmonicStructure = createTimeline(chords, createSequencingPosition(ticksPerBeat * signature.numerator, ticksPerBeat));
  var length = createSequencingPosition(chords.length * ticksPerBeat * signature.numerator, ticksPerBeat);
  harmonicStructure.setLength(length);
  // render the combination

  var rendered = renderSequence(harmonicStructure, baseSequence, signature, ticksPerBeat);

  // Test against expected

  expected.length = convertToPosition(expected.length, signature, ticksPerBeat)
  expected.sequence.forEach(function(element)
  {
    element.position = convertToPosition(element.position, signature, ticksPerBeat)
  });
//  console.log(">>>" + JSON.stringify(rendered,null ,2));
//  console.log("<<<" + JSON.stringify(expected,null ,2));
  assert.deepEqual(rendered, expected);
}

//==============================================================================

var baseSequence = {
    length : "1.4.1",
    sequence:
      [
        { position: "1.1.1", degrees: [{d:1, t:-12}, 1,2]},
        { position: "1.2.1", degrees: [2]},
        { position: "1.3.1", degrees: [3,1]},
      ]
    }

var progression = {
    root: "c3",
    scale: "major",
    degrees: [1,5]
}

var expected = {
  length: "3.1.1",
  sequence:
    [
      { position: "1.1.1", notes: [36, 48, 52]},
      { position: "1.2.1", notes: [52]},
      { position: "1.3.1", notes: [55, 48]},
      { position: "1.4.1", notes: [36, 48, 52]},
      { position: "2.1.1", notes: [43, 55, 59]},
      { position: "2.2.1", notes: [59]},
      { position: "2.3.1", notes: [62, 55]},
      { position: "2.4.1", notes: [43, 55, 59]},
    ]
}

var signature = new Signature;
testSequenceRendering(signature, baseSequence, progression, expected);

signature.numerator = 3;
var expectedOn3_4 = {
  length: "3.1.1",
  sequence:
    [
      { position: "1.1.1", notes: [36, 48, 52]},
      { position: "1.2.1", notes: [52]},
      { position: "1.3.1", notes: [55, 48]},
      { position: "2.1.1", notes: [43, 55, 59]},
      { position: "2.2.1", notes: [59]},
      { position: "2.3.1", notes: [62, 55]},
    ]
}

testSequenceRendering(signature, baseSequence, progression, expectedOn3_4);
<|endoftext|>


<commit_before>/*jshint expr: true*/
"use strict";
var chai = require("chai");
var chaiAsPromised = require("chai-as-promised");
var mockHelper = require("./helpers/mock_helper");
chai.use(chaiAsPromised);
var expect = chai.expect;
chai.config.includeStack = true;

describe("Alexa", function() {
  var Alexa = require("../index");
  describe("app", function() {
    describe("#request", function() {
      var mockRequest = mockHelper.load("intent_request_airport_info.json");
      var expectedMessage = "tubular";
      context("intent handler with shouldEndSession = false", function() {
        var app = new Alexa.app("myapp");
        var reqObject;
        var intentHandler = function(req, res) {
          res.say(expectedMessage).shouldEndSession(false);
          res.session("foo", true);
          res.session("bar", {
            qaz: "woah"
          });
          reqObject = req;
          return true;
        };
        app.intent("airportInfoIntent", {}, intentHandler);

        it("reponds with expected context applicationId", function() {
          return app.request(mockRequest).then((response) => {
            expect(reqObject.context).to
              .have.deep.property("System.application.applicationId", "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe");
          });
        });

        it("responds with a session object", function() {
          var subject = app.request(mockRequest).then(function(response) {
            return response.sessionAttributes;
          });
          return Promise.all([
            expect(subject).to.eventually.become({
              foo: true,
              bar: {
                qaz: "woah"
              }
            })
          ]);
        });

        it("has a res object with expected properties", function() {
          app.intent("airportInfoIntent", {}, intentHandler);
          var subject = app.request(mockRequest).then(function(response) {
            return reqObject;
          });
          return Promise.all([
            expect(subject).to.eventually.have
            .property("applicationId", "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"),
            expect(subject).to.eventually.have
            .property("userId", "amzn1.account.AM3B227HF3FAM1B261HK7FFM3A2")
          ]);
        });
      });
    });

    describe("#response", function() {
      var mockRequest = mockHelper.load("intent_request_airport_info.json");
      var expectedMessage = "tubular";
      context("intent handler with shouldEndSession = false", function() {
        var app = new Alexa.app("myapp");
        var intentHandler = function(req, res) {
          res.say(expectedMessage).shouldEndSession(false);
          res.session("foo", true);
          res.session("bar", {
            qaz: "woah"
          });
          res.clearSession();
          return true;
        };
        app.intent("airportInfoIntent", {}, intentHandler);

        it("responds with an empty session object after clearing session", function() {
          var subject = app.request(mockRequest).then(function(response) {
            return response.sessionAttributes;
          });
          return Promise.all([
            expect(subject).to.eventually.become({})
          ]);
        });
      });
    });

    describe("#response", function() {
      var mockRequest = mockHelper.load("intent_request_airport_info.json");
      var expectedMessage = "tubular";
      context("intent handler with shouldEndSession = false", function() {
        var app = new Alexa.app("myapp");
        var intentHandler = function(req, res) {
          res.say(expectedMessage).shouldEndSession(false);
          res.session("foo", true);
          res.session("bar", {
            qaz: "woah"
          });
          res.clearSession("bar");
          return true;
        };
        app.intent("airportInfoIntent", {}, intentHandler);

        it("responds with session object missing a cleared session variable", function() {
          var subject = app.request(mockRequest).then(function(response) {
            return response.sessionAttributes;
          });
          return Promise.all([
            expect(subject).to.eventually.become({ "foo": true })
          ]);
        });

      });
    });

    describe("#response", function() {
      var mockRequest = mockHelper.load("intent_request_airport_info.json");
      var expectedMessage = "tubular";
      context("intent handler with shouldEndSession = false", function() {
        var app = new Alexa.app("myapp");
        var intentHandler = function(req, res) {
          res.say(expectedMessage).shouldEndSession(false);
          res.session("bar", {
            qaz: "woah"
          });
          res.session("foo", res.session("bar"));
          return true;
        };
        app.intent("airportInfoIntent", {}, intentHandler);

        it("responds with a copied session object", function() {
          var subject = app.request(mockRequest).then(function(response) {
            return response.sessionAttributes["foo"];
          });
          return Promise.all([
            expect(subject).to.eventually.become({
              qaz: "woah"
            })
          ]);
        });
      });
    });

    describe("#response", function() {
      var mockRequest = mockHelper.load("intent_request_airport_info.json");
      var expectedMessage = "tubular";
      var expectedReprompt = "totally";
      context("intent handler with shouldEndSession = false", function() {
        var app = new Alexa.app("myapp");
        var intentHandler = function(req, res) {
          res.say(expectedMessage).shouldEndSession(false, expectedReprompt);
          return true;
        };
        app.intent("airportInfoIntent", {}, intentHandler);

        it("responds reprompted message on shouldEndSession", function() {
          var subject = app.request(mockRequest).then(function(response) {
            return response.response.reprompt.outputSpeech;
          });
          return expect(subject).to.eventually.become({
            ssml: "<speak>" + expectedReprompt + "</speak>",
            type: "SSML"
          });
        });
      });
    });

    describe("#request", function() {
      var mockRequest = mockHelper.load("audio_player_event_request.json");
      context("request without session", function() {
        var app = new Alexa.app("myapp");
        app.pre = function(req, res, type) {
          if (req.hasSession()) {
            // unreachable code, because the request doesn't have session
            req.getSession().set("foo", "bar");
          }
        };

        it("responds with an empty session object", function() {
          var subject = app.request(mockRequest).then(function(response) {
            return response.sessionAttributes;
          });
          return Promise.all([
            expect(subject).to.eventually.become({})
          ]);
        });

      });
    });

    describe("#request", function() {
      context("request without session", function() {
        var app, mockRequest;
        beforeEach(() => {
          mockRequest = mockHelper.load("audio_player_event_request.json");
          app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            req.getSession().clear();
          };
        });

        it("session.clear() should not throw", function() {
          app.request(mockRequest).should.eventually.succeed;
        });

      });
    });

    describe("#request", function() {
      context("request with session", function() {
        var app, mockRequest;
        beforeEach(() => {
          mockRequest = mockHelper.load("intent_request_airport_info.json");
          app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            req.getSession().clear();
          };
        });

        it("session.clear() should not throw", function() {
          app.request(mockRequest).should.eventually.succeed;
        });

      });
    });

    describe("#request", function() {
      context("request with session and attributes", function() {
        var app, mockRequest;
        beforeEach(() => {
          mockRequest = mockHelper.load("intent_request_airport_info_with_attributes.json");
          app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            req.getSession().clear();
          };
        });

        it("session.clear() should not throw", function() {
          app.request(mockRequest).should.eventually.succeed;
        });

      });
    });

    describe("#request", function() {
      var mockRequest = mockHelper.load("audio_player_event_request.json");
      context("request without session", function() {
        context("trying to get session variable", function() {
          var app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            req.getSession().get("foo");
          };
          describe("outputSpeech", function() {
            var subject = app.request(mockRequest).then(function(response) {
              return response.response.outputSpeech;
            });
            it("responds with NO_SESSION message", function() {
              return expect(subject).to.eventually.become({
                ssml: "<speak>" + app.messages.NO_SESSION + "</speak>",
                type: "SSML"
              });
            });
          });

        });

        context("trying to set session variable", function() {
          var app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            req.getSession().set("foo", "bar");
          };
          describe("outputSpeech", function() {
            var subject = app.request(mockRequest).then(function(response) {
              return response.response.outputSpeech;
            });
            it("responds with NO_SESSION message", function() {
              return expect(subject).to.eventually.become({
                ssml: "<speak>" + app.messages.NO_SESSION + "</speak>",
                type: "SSML"
              });
            });
          });

        });
      });
    });

  });
});
<commit_msg>Resolves matt-kruse/alexa-app#98 via tests that prove correct functionality<commit_after>/*jshint expr: true*/
"use strict";
var chai = require("chai");
var chaiAsPromised = require("chai-as-promised");
var mockHelper = require("./helpers/mock_helper");
chai.use(chaiAsPromised);
var expect = chai.expect;
chai.config.includeStack = true;

describe("Alexa", function() {
  var Alexa = require("../index");
  describe("app", function() {
    describe("#request", function() {
      var mockRequest = mockHelper.load("intent_request_airport_info.json");
      var expectedMessage = "tubular";
      context("intent handler with shouldEndSession = false", function() {
        var app = new Alexa.app("myapp");
        var reqObject;
        var intentHandler = function(req, res) {
          res.say(expectedMessage).shouldEndSession(false);
          res.session("foo", true);
          res.session("bar", {
            qaz: "woah"
          });
          reqObject = req;
          return true;
        };
        app.intent("airportInfoIntent", {}, intentHandler);

        it("reponds with expected context applicationId", function() {
          return app.request(mockRequest).then((response) => {
            expect(reqObject.context).to
              .have.deep.property("System.application.applicationId", "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe");
          });
        });

        it("responds with a session object", function() {
          var subject = app.request(mockRequest).then(function(response) {
            return response.sessionAttributes;
          });
          return Promise.all([
            expect(subject).to.eventually.become({
              foo: true,
              bar: {
                qaz: "woah"
              }
            })
          ]);
        });

        it("has a res object with expected properties", function() {
          app.intent("airportInfoIntent", {}, intentHandler);
          var subject = app.request(mockRequest).then(function(response) {
            return reqObject;
          });
          return Promise.all([
            expect(subject).to.eventually.have
            .property("applicationId", "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"),
            expect(subject).to.eventually.have
            .property("userId", "amzn1.account.AM3B227HF3FAM1B261HK7FFM3A2")
          ]);
        });
      });
    });

    describe("#response", function() {
      var mockRequest = mockHelper.load("intent_request_airport_info.json");
      var expectedMessage = "tubular";
      context("intent handler with shouldEndSession = false", function() {
        var app = new Alexa.app("myapp");
        var intentHandler = function(req, res) {
          res.say(expectedMessage).shouldEndSession(false);
          res.session("foo", true);
          res.session("bar", {
            qaz: "woah"
          });
          res.clearSession();
          return true;
        };
        app.intent("airportInfoIntent", {}, intentHandler);

        it("responds with an empty session object after clearing session", function() {
          var subject = app.request(mockRequest).then(function(response) {
            return response.sessionAttributes;
          });
          return Promise.all([
            expect(subject).to.eventually.become({})
          ]);
        });
      });
    });

    describe("#response", function() {
      var mockRequest = mockHelper.load("intent_request_airport_info.json");
      var expectedMessage = "tubular";
      context("intent handler with shouldEndSession = false", function() {
        var app = new Alexa.app("myapp");
        var intentHandler = function(req, res) {
          res.say(expectedMessage).shouldEndSession(false);
          res.session("foo", true);
          res.session("bar", {
            qaz: "woah"
          });
          res.clearSession("bar");
          return true;
        };
        app.intent("airportInfoIntent", {}, intentHandler);

        it("responds with session object missing a cleared session variable", function() {
          var subject = app.request(mockRequest).then(function(response) {
            return response.sessionAttributes;
          });
          return Promise.all([
            expect(subject).to.eventually.become({ "foo": true })
          ]);
        });

      });
    });

    describe("#response", function() {
      var mockRequest = mockHelper.load("intent_request_airport_info.json");
      var expectedMessage = "tubular";
      context("intent handler with shouldEndSession = false", function() {
        var app = new Alexa.app("myapp");
        var intentHandler = function(req, res) {
          res.say(expectedMessage).shouldEndSession(false);
          res.session("bar", {
            qaz: "woah"
          });
          res.session("foo", res.session("bar"));
          return true;
        };
        app.intent("airportInfoIntent", {}, intentHandler);

        it("responds with a copied session object", function() {
          var subject = app.request(mockRequest).then(function(response) {
            return response.sessionAttributes["foo"];
          });
          return Promise.all([
            expect(subject).to.eventually.become({
              qaz: "woah"
            })
          ]);
        });
      });
    });

    describe("#response", function() {
      var mockRequest = mockHelper.load("intent_request_airport_info.json");
      var expectedMessage = "tubular";
      var expectedReprompt = "totally";
      context("intent handler with shouldEndSession = false", function() {
        var app = new Alexa.app("myapp");
        var intentHandler = function(req, res) {
          res.say(expectedMessage).shouldEndSession(false, expectedReprompt);
          return true;
        };
        app.intent("airportInfoIntent", {}, intentHandler);

        it("responds reprompted message on shouldEndSession", function() {
          var subject = app.request(mockRequest).then(function(response) {
            return response.response.reprompt.outputSpeech;
          });
          return expect(subject).to.eventually.become({
            ssml: "<speak>" + expectedReprompt + "</speak>",
            type: "SSML"
          });
        });
      });
    });

    describe("#request", function() {
      var mockRequest = mockHelper.load("audio_player_event_request.json");
      context("request without session", function() {
        var app = new Alexa.app("myapp");
        app.pre = function(req, res, type) {
          if (req.hasSession()) {
            // unreachable code, because the request doesn't have session
            req.getSession().set("foo", "bar");
          }
        };

        it("responds with an empty session object", function() {
          var subject = app.request(mockRequest).then(function(response) {
            return response.sessionAttributes;
          });
          return Promise.all([
            expect(subject).to.eventually.become({})
          ]);
        });

      });
    });

    describe("#request", function() {
      context("request without session", function() {
        var app, mockRequest;
        beforeEach(() => {
          mockRequest = mockHelper.load("audio_player_event_request.json");
          app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            req.getSession().clear();
          };
        });

        it("session.clear() should not throw", function() {
          app.request(mockRequest).should.eventually.succeed;
        });

      });
    });

    describe("#request", function() {
      context("request without session", function() {
        var app, mockRequest, returnedAttributeValue;
        beforeEach(() => {
          returnedAttributeValue = "INITIAL TEST VALUE WHICH SHOULD BE OVERRIDDEN";
          mockRequest = mockHelper.load("audio_player_event_request.json");
          app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            returnedAttributeValue = req.getSession().get("AttributeWhichDoesNotExist");
          };
        });

        it("session.get(key) should not throw if attribute is not present", function() {
          return app.request(mockRequest)
            .then(() => returnedAttributeValue.should.equal(undefined))
            .should.eventually.succeed;
        });

      });
    });

    describe("#request", function() {
      context("request with session", function() {
        var app, mockRequest, returnedAttributeValue;
        beforeEach(() => {
          returnedAttributeValue = "INITIAL TEST VALUE WHICH SHOULD BE OVERRIDDEN";
          mockRequest = mockHelper.load("intent_request_airport_info.json");
          app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            returnedAttributeValue = req.getSession().get("AttributeWhichDoesNotExist");
          };
        });

        it("session.get(key) should not throw if attribute is not present", function() {
          return app.request(mockRequest)
            .then(() => returnedAttributeValue.should.equal(undefined))
            .should.eventually.succeed;
        });

      });
    });

    describe("#request", function() {
      context("request with session", function() {
        var app, mockRequest, returnedAttributeValue;
        beforeEach(() => {
          returnedAttributeValue = "INITIAL TEST VALUE WHICH SHOULD BE OVERRIDDEN";
          mockRequest = mockHelper.load("intent_request_airport_info_with_attributes.json");
          app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            returnedAttributeValue = req.getSession().get("AttributeWhichDoesNotExist");
          };
        });

        it("session.get(key) should not throw if attribute is not present", function() {
          return app.request(mockRequest)
            .then(() => returnedAttributeValue.should.equal(undefined))
            .should.eventually.succeed;
        });

      });
    });

    describe("#request", function() {
      context("request with session", function() {
        var app, mockRequest;
        beforeEach(() => {
          mockRequest = mockHelper.load("intent_request_airport_info.json");
          app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            req.getSession().clear();
          };
        });

        it("session.clear() should not throw", function() {
          app.request(mockRequest).should.eventually.succeed;
        });

      });
    });

    describe("#request", function() {
      context("request with session and attributes", function() {
        var app, mockRequest;
        beforeEach(() => {
          mockRequest = mockHelper.load("intent_request_airport_info_with_attributes.json");
          app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            req.getSession().clear();
          };
        });

        it("session.clear() should not throw", function() {
          app.request(mockRequest).should.eventually.succeed;
        });

      });
    });

    describe("#request", function() {
      var mockRequest = mockHelper.load("audio_player_event_request.json");
      context("request without session", function() {
        context("trying to get session variable", function() {
          var app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            req.getSession().get("foo");
          };
          describe("outputSpeech", function() {
            var subject = app.request(mockRequest).then(function(response) {
              return response.response.outputSpeech;
            });
            it("responds with NO_SESSION message", function() {
              return expect(subject).to.eventually.become({
                ssml: "<speak>" + app.messages.NO_SESSION + "</speak>",
                type: "SSML"
              });
            });
          });

        });

        context("trying to set session variable", function() {
          var app = new Alexa.app("myapp");
          app.pre = function(req, res, type) {
            req.getSession().set("foo", "bar");
          };
          describe("outputSpeech", function() {
            var subject = app.request(mockRequest).then(function(response) {
              return response.response.outputSpeech;
            });
            it("responds with NO_SESSION message", function() {
              return expect(subject).to.eventually.become({
                ssml: "<speak>" + app.messages.NO_SESSION + "</speak>",
                type: "SSML"
              });
            });
          });

        });
      });
    });

  });
});
<|endoftext|>


<commit_before>/**
 * Embed plugin by gohabereg
 * @version 1.0.0
 */
var embed = function(embed){

    var methods = {

        addInternal: function (content) {
            codex.content.switchBlock(codex.content.currentNode, content, 'embed');

            var blockContent = codex.content.currentNode.childNodes[0];
            blockContent.classList.add('embed__loader');

            setTimeout(function(){
                blockContent.classList.remove('embed__loader');
            }, 1000);

        },

        getHtmlWithEmbedId: function (type, id) {
            return services[type].html.replace(/<\%\= remote\_id \%\>/g, id);
        },

        makeElementFromHtml: function(html) {
            var wrapper = document.createElement('DIV');

            wrapper.innerHTML = html;

            return wrapper;
        },

        getRemoteId: function(source, execArray) {

            switch(source) {
                case 'yandex-music-track':
                    id = execArray[2]+'/'+execArray[1];
                    break;
                case 'yandex-music-playlist':
                    id = execArray[1]+'/'+execArray[2];
                    break;
                default:
                    id = execArray[1];
            }

            return id;
        }
    };

    var services = {
        vimeo: {
            regex: /(?:http[s]?:\/\/)?(?:www.)?vimeo\.co(?:.+\/([^\/]\d+)(?:#t=[\d]+)?s?$)/,
            html: "<iframe src=\"https://player.vimeo.com/video/<%= remote_id %>?title=0&byline=0\" width=\"580\" height=\"320\" frameborder=\"0\">",
            height: 320,
            width: 580

        },
        youtube: {
            regex: /^.*(?:(?:youtu\.be\/)|(?:youtube\.com)\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*)(?:[\?\&]t\=(\d*)|)/,
            html: "<iframe src=\"https://www.youtube.com/embed/<%= remote_id %>\" width=\"580\" height=\"320\" frameborder=\"0\" allowfullscreen>",
            height: 320,
            width: 580
        },
        coub: {
            regex: /https?:\/\/coub\.com\/view\/([^\/\?\&]+)/,
            html: "<iframe src=\"//coub.com/embed/<%= remote_id %>\" width=\"580\" height=\"320\" frameborder=\"0\" allowfullscreen>",
            height: 320,
            width: 580
        },
        vine: {
            regex: /https?:\/\/vine\.co\/v\/([^\/\?\&]+)/,
            html: "<iframe src=\"https://vine.co/v/<%= remote_id %>/embed/simple/\" width=\"580\" height=\"320\" frameborder=\"0\" allowfullscreen>",
            height: 320,
            width: 580
        },
        imgur: {
            regex: /https?:\/\/(?:i\.)?imgur\.com.*\/([a-zA-Z0-9]+)(?:\.gifv)?/,
            html: "<iframe allowfullscreen=\"true\" scrolling=\"no\" src=\"http://imgur.com/<%= remote_id %>/embed\" id=\"imgur-embed-iframe-pub-<%= remote_id %>\" class=\"imgur-embed-iframe-pub\" style=\"height: 500px; width: 540px; border: 1px solid #000\">",
            height: 500,
            width: 540
        },
        gfycat: {
            regex: /https?:\/\/gfycat\.com(?:\/detail)?\/([a-zA-Z]+)/,
            html: "<iframe src='https://gfycat.com/ifr/<%= remote_id %>' frameborder='0' scrolling='no' width='580' height='436' allowfullscreen >",
            height: 436,
            width: 580
        },
        'twitch-channel': {
            regex: /https?:\/\/twitch.tv\/([^\/\?\&]*)/,
            html: "<iframe src=\"https://player.twitch.tv/?channel=<%= remote_id %>\" frameborder=\"0\" allowfullscreen=\"true\" scrolling=\"no\" height=\"366\" width=\"600\">",
            height: 366,
            width: 600
        },
        'twitch-video': {
            regex: /https?:\/\/www.twitch.tv\/[^\/\?\&]*\/v\/([0-9]*)/,
            html: "<iframe src=\"https://player.twitch.tv/?video=v<%= remote_id %>\" frameborder=\"0\" allowfullscreen=\"true\" scrolling=\"no\" height=\"366\" width=\"600\">",
            height: 366,
            width: 600
        },
        'yandex-music-album': {
            regex: /https?:\/\/music.yandex.ru\/album\/([0-9]*)/,
            html: "<iframe frameborder=\"0\" style=\"border:none;width:540px;height:400px;\" width=\"540\" height=\"400\" src=\"https://music.yandex.ru/iframe/#album/<%= remote_id %>/\">",
            height: 400,
            width: 540
        },
        'yandex-music-track': {
            regex: /https?:\/\/music.yandex.ru\/album\/([0-9]*)\/track\/([0-9]*)/,
            html: "<iframe frameborder=\"0\" style=\"border:none;width:540px;height:100px;\" width=\"540\" height=\"100\" src=\"https://music.yandex.ru/iframe/#track/<%= remote_id %>/\">",
            height: 100,
            width: 540
        },
        'yandex-music-playlist': {
            regex: /https?:\/\/music.yandex.ru\/users\/([^\/\?\&]*)\/playlists\/([0-9]*)/,
            html: "<iframe frameborder=\"0\" style=\"border:none;width:540px;height:400px;\" width=\"540\" height=\"400\" src=\"https://music.yandex.ru/iframe/#playlist/<%= remote_id %>/show/cover/description/\">",
            height: 400,
            width: 540
        }
    };

    embed.make = function(data, isInternal) {

        if (!data.remote_id)
            return;

        var html  = methods.getHtmlWithEmbedId(data.source, data.remote_id),
            block = methods.makeElementFromHtml(html);

        block.dataset.remoteId = data.remote_id;
        block.dataset.source = data.source;
        block.dataset.thumbnailUrl = data.thumbnailUrl;

        block.classList.add('embed');

        var sidePadding = (600 - services[data.source].width) / 2 + 'px';

        block.style.padding = '30px ' + sidePadding;

        if (isInternal) {
                methods.addInternal(block);
        }

        return block;

    };

    /**
     * Saving JSON output.
     * Upload data via ajax
     */
    embed.save = function(blockContent) {

        if (!blockContent)
            return;

        var data,
            source = blockContent.dataset.source;

        data = {
            source: source,
            remote_id: blockContent.dataset.remoteId,
            thumbnailUrl: blockContent.dataset.thumbnailUrl,
            height: services[source].height,
            width: services[source].width
        };

        return data;

    };

    /**
     * Render data
     */
    embed.render = function(data) {
        return embed.make(data);
    };

    embed.urlPastedCallback = function(url, pattern) {

        var execArray = pattern.regex.exec(url),
            id = methods.getRemoteId(pattern.type, execArray);

        var data = {
            source: pattern.type,
            remote_id: id,
            thumbnailUrl: url
        };

        embed.make(data, true);
    };

    embed.validate = function(savedData) {

        var source = savedData.source,
            execArray = services[source].regex.exec(savedData.thumbnailUrl),
            remoteId = methods.getRemoteId(source, execArray);

        return remoteId == savedData.remote_id;

    };

    return embed;

}({});<commit_msg>vk support<commit_after>/**
 * Embed plugin by gohabereg
 * @version 1.0.0
 */
var embed = function(embed){

    var methods = {

        addInternal: function (content) {
            codex.content.switchBlock(codex.content.currentNode, content, 'embed');

            var blockContent = codex.content.currentNode.childNodes[0];
            blockContent.classList.add('embed__loader');

            setTimeout(function(){
                blockContent.classList.remove('embed__loader');
            }, 1000);

        },

        getHtmlWithEmbedId: function (type, id) {
            return services[type].html.replace(/<\%\= remote\_id \%\>/g, id);
        },

        makeElementFromHtml: function(html) {
            var wrapper = document.createElement('DIV');

            wrapper.innerHTML = html;

            return wrapper;
        },

        getRemoteId: function(source, execArray) {

            switch(source) {
                case 'yandex-music-track':
                    id = execArray[2]+'/'+execArray[1];
                    break;
                case 'yandex-music-playlist':
                    id = execArray[1]+'/'+execArray[2];
                    break;
                default:
                    id = execArray[1];
            }

            return id;
        }
    };

    var services = {
        vimeo: {
            regex: /(?:http[s]?:\/\/)?(?:www.)?vimeo\.co(?:.+\/([^\/]\d+)(?:#t=[\d]+)?s?$)/,
            html: "<iframe src=\"https://player.vimeo.com/video/<%= remote_id %>?title=0&byline=0\" width=\"580\" height=\"320\" frameborder=\"0\">",
            height: 320,
            width: 580

        },
        youtube: {
            regex: /^.*(?:(?:youtu\.be\/)|(?:youtube\.com)\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*)(?:[\?\&]t\=(\d*)|)/,
            html: "<iframe src=\"https://www.youtube.com/embed/<%= remote_id %>\" width=\"580\" height=\"320\" frameborder=\"0\" allowfullscreen>",
            height: 320,
            width: 580
        },
        vk : {
            regex: /^https?.+vk?.com\/feed\?w=wall\d+_\d+/,
            html: "<iframe src=\"https://tjournal.ru/proxy/video/<%= remote_id %>?rel=0&showinfo=0&enablejsapi=1&autoplay=1\" width=\"580\" height=\"320\" frameborder=\"0\" allowfullscreen>"
        },
        coub: {
            regex: /https?:\/\/coub\.com\/view\/([^\/\?\&]+)/,
            html: "<iframe src=\"//coub.com/embed/<%= remote_id %>\" width=\"580\" height=\"320\" frameborder=\"0\" allowfullscreen>",
            height: 320,
            width: 580
        },
        vine: {
            regex: /https?:\/\/vine\.co\/v\/([^\/\?\&]+)/,
            html: "<iframe src=\"https://vine.co/v/<%= remote_id %>/embed/simple/\" width=\"580\" height=\"320\" frameborder=\"0\" allowfullscreen>",
            height: 320,
            width: 580
        },
        imgur: {
            regex: /https?:\/\/(?:i\.)?imgur\.com.*\/([a-zA-Z0-9]+)(?:\.gifv)?/,
            html: "<iframe allowfullscreen=\"true\" scrolling=\"no\" src=\"http://imgur.com/<%= remote_id %>/embed\" id=\"imgur-embed-iframe-pub-<%= remote_id %>\" class=\"imgur-embed-iframe-pub\" style=\"height: 500px; width: 540px; border: 1px solid #000\">",
            height: 500,
            width: 540
        },
        gfycat: {
            regex: /https?:\/\/gfycat\.com(?:\/detail)?\/([a-zA-Z]+)/,
            html: "<iframe src='https://gfycat.com/ifr/<%= remote_id %>' frameborder='0' scrolling='no' width='580' height='436' allowfullscreen >",
            height: 436,
            width: 580
        },
        'twitch-channel': {
            regex: /https?:\/\/twitch.tv\/([^\/\?\&]*)/,
            html: "<iframe src=\"https://player.twitch.tv/?channel=<%= remote_id %>\" frameborder=\"0\" allowfullscreen=\"true\" scrolling=\"no\" height=\"366\" width=\"600\">",
            height: 366,
            width: 600
        },
        'twitch-video': {
            regex: /https?:\/\/www.twitch.tv\/[^\/\?\&]*\/v\/([0-9]*)/,
            html: "<iframe src=\"https://player.twitch.tv/?video=v<%= remote_id %>\" frameborder=\"0\" allowfullscreen=\"true\" scrolling=\"no\" height=\"366\" width=\"600\">",
            height: 366,
            width: 600
        },
        'yandex-music-album': {
            regex: /https?:\/\/music.yandex.ru\/album\/([0-9]*)/,
            html: "<iframe frameborder=\"0\" style=\"border:none;width:540px;height:400px;\" width=\"540\" height=\"400\" src=\"https://music.yandex.ru/iframe/#album/<%= remote_id %>/\">",
            height: 400,
            width: 540
        },
        'yandex-music-track': {
            regex: /https?:\/\/music.yandex.ru\/album\/([0-9]*)\/track\/([0-9]*)/,
            html: "<iframe frameborder=\"0\" style=\"border:none;width:540px;height:100px;\" width=\"540\" height=\"100\" src=\"https://music.yandex.ru/iframe/#track/<%= remote_id %>/\">",
            height: 100,
            width: 540
        },
        'yandex-music-playlist': {
            regex: /https?:\/\/music.yandex.ru\/users\/([^\/\?\&]*)\/playlists\/([0-9]*)/,
            html: "<iframe frameborder=\"0\" style=\"border:none;width:540px;height:400px;\" width=\"540\" height=\"400\" src=\"https://music.yandex.ru/iframe/#playlist/<%= remote_id %>/show/cover/description/\">",
            height: 400,
            width: 540
        }
    };

    embed.make = function(data, isInternal) {

        if (!data.remote_id)
            return;

        var html  = methods.getHtmlWithEmbedId(data.source, data.remote_id),
            block = methods.makeElementFromHtml(html);

        block.dataset.remoteId = data.remote_id;
        block.dataset.source = data.source;
        block.dataset.thumbnailUrl = data.thumbnailUrl;

        block.classList.add('embed');

        var sidePadding = (600 - services[data.source].width) / 2 + 'px';

        block.style.padding = '30px ' + sidePadding;

        if (isInternal) {
                methods.addInternal(block);
        }

        return block;

    };

    /**
     * Saving JSON output.
     * Upload data via ajax
     */
    embed.save = function(blockContent) {

        if (!blockContent)
            return;

        var data,
            source = blockContent.dataset.source;

        data = {
            source: source,
            remote_id: blockContent.dataset.remoteId,
            thumbnailUrl: blockContent.dataset.thumbnailUrl,
            height: services[source].height,
            width: services[source].width
        };

        return data;

    };

    /**
     * Render data
     */
    embed.render = function(data) {
        return embed.make(data);
    };

    embed.urlPastedCallback = function(url, pattern) {

        var execArray = pattern.regex.exec(url),
            id = methods.getRemoteId(pattern.type, execArray);

        var data = {
            source: pattern.type,
            remote_id: id,
            thumbnailUrl: url
        };

        embed.make(data, true);
    };

    embed.validate = function(savedData) {

        var source = savedData.source,
            execArray = services[source].regex.exec(savedData.thumbnailUrl),
            remoteId = methods.getRemoteId(source, execArray);

        return remoteId == savedData.remote_id;

    };

    return embed;

}({});<|endoftext|>


<commit_before>var oauth = require('oauth');
var _     = require('lodash');
var async = require('async');

var db = require('../db/content-provider');
var timelineUtils = require('../utils/timeline-utils');

require('dotenv').load();

var _oauth = new oauth.OAuth(
    null,
    null,
    process.env.CONSUMER_KEY_BITBUCKET,
    process.env.CONSUMER_SECRET_BITBUCKET,
    '1.0',
    null,
    'HMAC-SHA1'
);

_oauth.get(
    'https://bitbucket.org/api/2.0/repositories/' + process.env.BITBUCKET_USERNAME,
    null,
    null,
    function(err, data, res) {
        if (err) {
            console.log(err);
        }

        var asJson = JSON.parse(data);
        var teams = asJson['values'];
        var hrefs = _.map(teams, function(item) {
            return item['links']['commits']['href'];
        });

        _.forEach(hrefs, function(item) {
            repositoriesCollection.insert({uri: item});
        });

        fetchUrlCommitsReposForTeams();
    }
);

var fetchUrlCommitsReposForTeams = function() {
    _oauth.get(
        'https://api.bitbucket.org/2.0/teams/?role=member',
        null,
        null,
        function(err, data, res) {
            if (err) {
                console.log(err);
            }

            var asJson = JSON.parse(data);
            var teams = asJson['values'];
            var nbTeamsToCheck = teams.length;
            var hrefs = _.map(teams, function(item) {
                return item['links']['repositories']['href'];
            });

            var fcts = _.map(hrefs, function(item) {
                return function(callback) {
                    getReposTeams(item, callback);
                }
            });

            async.parallel(fcts, function(err, res) {
                if (err) {
                    console.log(err);
                }

                getCommitsRepos();
            });
        }
    );
}

var getReposTeams = function(url, callback) {
    _oauth.get(
        url,
        null,
        null,
        function(err, data, res) {
            if (err) {
                console.log(err);
            }
            var values = JSON.parse(data)['values'];
            var links = _.forEach(values, function(item) {
                var uriCommits = item['links']['commits']['href'];
                repositoriesCollection.insert({uri: uriCommits});
            });

            callback(null, links);
        }
    );
}

var getCommitsRepos = function() {
    var repos = repositoriesCollection.where(function(item) {
        return item.uri !== null;
    });

    var fcts = _.map(repos, function(item) {
        return function(callback) {
            getCommits(item.uri, callback);
        }
    });

    async.parallel(fcts, function(err, res) {
        if (err) {
            console.log(err);
        }

        db.saveDatabase();
        console.log(timelineUtils.getCommitsPerDay(commitsCollection, 'bitbucket'));
    });
}

var getCommits = function(_uri, callback) {
    _oauth.get(
        _uri,
        null,
        null,
        function(err, data, res) {
            if (err) {
                console.log(err);
            }

            var asJson = JSON.parse(data);
            var commits = asJson['values'];
            var _commits = _.forEach(commits, function(elem) {
                var author = elem['author']['user'];
                if (author && author['username'] === process.env.BITBUCKET_USERNAME) {
                    commitsCollection.insert({node: elem['hash'], timestamp: elem['date'], uri: _uri, provider: 'bitbucket'});
                }
            });

            callback(null, _uri);
        }
    );
}

var getCommitsPerDay = function() {
    var mapTimestamp = function(obj) {
        return obj.timestamp;
    };

    var reduceToSameDay = function(timestamps) {
        return _.groupBy(timestamps, function(timestamp) {
            return timestamp.split('T')[0];
        });
    }

    commitsPerDay = commitsCollection.mapReduce(mapTimestamp, reduceToSameDay);
    return _.map(commitsPerDay, function(item, key) {
        return {'date': key, 'num_commits': item.length};
    });
}
<commit_msg>use callback on error<commit_after>var oauth = require('oauth');
var _     = require('lodash');
var async = require('async');

var db = require('../db/content-provider');
var timelineUtils = require('../utils/timeline-utils');

require('dotenv').load();

var _oauth = new oauth.OAuth(
    null,
    null,
    process.env.CONSUMER_KEY_BITBUCKET,
    process.env.CONSUMER_SECRET_BITBUCKET,
    '1.0',
    null,
    'HMAC-SHA1'
);

_oauth.get(
    'https://bitbucket.org/api/2.0/repositories/' + process.env.BITBUCKET_USERNAME,
    null,
    null,
    function(err, data, res) {
        if (err) {
            console.log(err);
        }

        var asJson = JSON.parse(data);
        var teams = asJson['values'];
        var hrefs = _.map(teams, function(item) {
            return item['links']['commits']['href'];
        });

        _.forEach(hrefs, function(item) {
            repositoriesCollection.insert({uri: item});
        });

        fetchUrlCommitsReposForTeams();
    }
);

var fetchUrlCommitsReposForTeams = function() {
    _oauth.get(
        'https://api.bitbucket.org/2.0/teams/?role=member',
        null,
        null,
        function(err, data, res) {
            if (err) {
                console.log(err);
            }

            var asJson = JSON.parse(data);
            var teams = asJson['values'];
            var nbTeamsToCheck = teams.length;
            var hrefs = _.map(teams, function(item) {
                return item['links']['repositories']['href'];
            });

            var fcts = _.map(hrefs, function(item) {
                return function(callback) {
                    getReposTeams(item, callback);
                }
            });

            async.parallel(fcts, function(err, res) {
                if (err) {
                    console.log(err);
                }

                getCommitsRepos();
            });
        }
    );
}

var getReposTeams = function(url, callback) {
    _oauth.get(
        url,
        null,
        null,
        function(err, data, res) {
            if (err) {
                console.log(err);
            }
            var values = JSON.parse(data)['values'];
            var links = _.forEach(values, function(item) {
                var uriCommits = item['links']['commits']['href'];
                repositoriesCollection.insert({uri: uriCommits});
            });

            callback(null, links);
        }
    );
}

var getCommitsRepos = function() {
    var repos = repositoriesCollection.where(function(item) {
        return item.uri !== null;
    });

    var fcts = _.map(repos, function(item) {
        return function(callback) {
            getCommits(item.uri, callback);
        }
    });

    async.parallel(fcts, function(err, res) {
        if (err) {
            console.log(err);
        }

        db.saveDatabase();
        console.log(timelineUtils.getCommitsPerDay(commitsCollection, 'bitbucket'));
    });
}

var getCommits = function(_uri, callback) {
    _oauth.get(
        _uri,
        null,
        null,
        function(err, data, res) {
            if (err) {
                callback(err, null);
            }

            var asJson = JSON.parse(data);
            var commits = asJson['values'];
            var _commits = _.forEach(commits, function(elem) {
                var author = elem['author']['user'];
                if (author && author['username'] === process.env.BITBUCKET_USERNAME) {
                    commitsCollection.insert({node: elem['hash'], timestamp: elem['date'], uri: _uri, provider: 'bitbucket'});
                }
            });

            callback(null, _uri);
        }
    );
}

var getCommitsPerDay = function() {
    var mapTimestamp = function(obj) {
        return obj.timestamp;
    };

    var reduceToSameDay = function(timestamps) {
        return _.groupBy(timestamps, function(timestamp) {
            return timestamp.split('T')[0];
        });
    }

    commitsPerDay = commitsCollection.mapReduce(mapTimestamp, reduceToSameDay);
    return _.map(commitsPerDay, function(item, key) {
        return {'date': key, 'num_commits': item.length};
    });
module.exports = {
    fetchContributionsOnBitbucket: fetchContributionsOnBitbucket
}
<|endoftext|>


<commit_before>/*jslint browser: true, nomen: true */

(function (flow, $, girder) {
    'use strict';

    $(document).ready(function () {
        girder.apiRoot = '/girder/api/v1';
        var app = new flow.App({
            el: 'body'
        });

        // Lookup the ID of the analysis that we wish to perform.
        app.analysisName = "PGLS_2traits-app";
        girder.restRequest({
            path: 'resource/search',
            data: {
                q: app.analysisName,
                types: JSON.stringify(["item"])
            }
        }).done(function (results) {
            app.analysisId = results["item"][0]._id;
            app.readyToAnalyze();
        });

        app.readyToAnalyze = function () {
            if ("column_x" in this && "column_y" in this && "table" in this && "tree" in this &&
                "analysisId" in this) {
                d3.select("#analyze").classed('disabled', false);
            }
        };

        function toggleInputTablePreview() {
            if ($("#table-preview-icon").hasClass("glyphicon-folder-close")) {
                $("#table-preview-icon").removeClass("glyphicon-folder-close");
                $("#table-preview-icon").addClass("glyphicon-folder-open");
                $("#table-preview-text").text(" Hide input table preview");
            }
            else {
                $("#table-preview-icon").removeClass("glyphicon-folder-open");
                $("#table-preview-icon").addClass("glyphicon-folder-close");
                $("#table-preview-text").text(" Show input table preview");
            }

            $("#input-table-vis").toggle('slow');
        }

        // override upload function for simple mode
        flow.DatasetManagementView.prototype.upload = function (file) {
            var reader = new FileReader();

            reader.onload = _.bind(function (e) {
                var dataset = {
                        name: file.name,
                        data: e.target.result
                    },
                    extension = file.name.split('.'),
                    typeFormat;

                extension = extension[extension.length - 1];
                typeFormat = flow.getTypeFormatsFromExtension(extension)[0];
                typeFormat = {type: typeFormat.type, format: typeFormat.format};
                _.extend(dataset, typeFormat);
                dataset = new Backbone.Model(dataset);

                // modifications for simple app begin here
                // if its a table, get the column names
                if (typeFormat.type == "table") {
                    app.table = dataset.get('data');
                    app.tableFormat = typeFormat.format;
                    d3.select("#table-name").html('Table: ' + file.name + ' ');
                    $("#column-input").text("Parsing column names...");
                    $("#column-names").empty();
                    flow.retrieveDatasetAsFormat(dataset, "table", "column.names", false, _.bind(function (error, dataset) {
                        var columnNames = dataset.get('data');
                        for (var i = 0; i < columnNames.length; ++i) {
                            // create drag-and-drop elements here
                            $("#column-names").append('
' + columnNames[i] + '
');
                        }
                        $(".draggable").draggable({
                             zIndex: 1, helper: "clone"
                        });
                        d3.select("#column-input").html('Drag column of interest here ');
                    }, this));

                    flow.retrieveDatasetAsFormat(dataset, "table", "rows", false, _.bind(function (error, dataset) {
                      // show the input table to help the user understand if their data
                      // was parsed correctly or not
                      var rowData = dataset.get('data');
                      rowData.rows = rowData.rows.slice(0, 3);
                      d3.select("#input-table-vis-container").classed('hidden', false);
                      $("#input-table-vis").table({ data: rowData });
                      d3.select("#column-input-y").html('Drag response variable (Y) here ');
                      d3.select("#column-input-x").html('Drag predictor variable (X) here ');
                    }, this));

                }

                else if (typeFormat.type == "tree") {
                    app.tree = dataset.get('data');
                    d3.select("#tree-name").html('Tree: ' + file.name + ' ');
                }
                app.readyToAnalyze();

                this.datasets.off('add', null, 'set-collection').add(dataset);
            }, this);

            reader.readAsText(file);
        };

        $("#column-input-y").droppable({
            drop: function( event, ui ) {
                var COI = ui.draggable.text();
                app.column_y = COI;
                d3.select("#column-input-y")
                    .classed('btn-primary', true)
                    .classed('btn-success', false)
                    .classed('bg-warning', false)
                    .html(COI + ' ' + " (Y) ~");
                app.readyToAnalyze();
            },
            over: function (event, ui) {
                d3.select("#column-input-y")
                    .classed('btn-success', true)
                    .classed('bg-warning', false);
            },
            out: function (event, ui) {
                d3.select("#column-input-y")
                    .classed('btn-success', false)
                    .classed('bg-warning', true);
            }
            });

            $("#column-input-x").droppable({
                drop: function( event, ui ) {
                    var COI = ui.draggable.text();
                    app.column_x = COI;
                    d3.select("#column-input-x")
                        .classed('btn-primary', true)
                        .classed('btn-success', false)
                        .classed('bg-warning', false)
                        .html(COI + ' ' + " (X)");
                    app.readyToAnalyze();
                },
                over: function (event, ui) {
                    d3.select("#column-input-x")
                        .classed('btn-success', true)
                        .classed('bg-warning', false);
                },
                out: function (event, ui) {
                    d3.select("#column-input-x")
                        .classed('btn-success', false)
                        .classed('bg-warning', true);
                }
                });

        function toggleCorrelationModel() {

                  if(document.getElementById("first_toggle").checked)
                  {
                    app.correlation="BM";
                  }
                  if(document.getElementById("second_toggle").checked)
                  {
                    app.correlation="OU";
                  }
                  if(document.getElementById("third_toggle").checked)
                  {
                    app.correlation="lambda";
                  }
        }

        $("#analyze").click(function() {
            $("#analyze").attr("disabled", "disabled");
            $("#analyze").text("Re-run");
            $("#notice").text("Performing analysis...");

            toggleCorrelationModel();

            var inputs = {
                table:  {type: "table",  format: app.tableFormat,    data: app.table},
                tree:   {type: "tree",   format: "newick",           data: app.tree},
                dep_variable: {type: "string", format: "text",             data: app.column_y},
                ind_variable: {type: "string", format: "text",             data: app.column_x},
                correlation: {type: "string", format: "text",             data: app.correlation}
            };

            var outputs = {
				        coefficients: {type: "table", format: "rows"},
                pglsPlot: {type: "image", format: "png.base64"},
                modelfit_summary: {type: "table", format: "rows"}
            };

            flow.performAnalysis(app.analysisId, inputs, outputs,
                _.bind(function (error, result) {
                    app.taskId = result._id;
                    setTimeout(_.bind(app.checkResult, app), 1000);
                }, app));

        app.checkResult = function () {
            var check_url = '/item/' + this.analysisId + '/flow/' + this.taskId + '/status'
            girder.restRequest({path: check_url}).done(_.bind(function (result) {
                console.log(result.status);
                if (result.status === 'SUCCESS') {
                    // get result data
                    var result_url = '/item/' + this.ASRId + '/flow/' + this.taskId + '/result'
                    girder.restRequest({path: result_url}).done(_.bind(function (data) {
                        app.modelPlot = data.result.pglsPlot.data;
                      // render tree plot
                      $("#model-plot").image({ data: app.modelPlot });
                      $("#analyze").removeAttr("disabled");
                      $("#notice").text("Analysis succeeded!");
                      $('html, body').animate({
                          scrollTop: $("#model-plot").offset().top
                      }, 1000);

                      var coeffTable = data.result.coefficients.data.rows;
                      var modelTable = data.result.modelfit_summary.data.rows;
                      console.log(modelTable);

                      // pretty results
                      $("#result").append("
Results:<\h2>");
                      $("#result").append("Equation fit:
");
                      $("#result").append(app.column_y," = ", app.column_x, "

");
                      $("#result").append("Model for residuals: ", app.correlation, "

");
                      if(app.correlation == "OU")
                        $("#result").append("alpha = ", coeffTable[2]["Value"].toFixed(3));
                      $("#result").append("
Coefficients:<\h3>
");
                      $("#result").append("Intercept =  ", coeffTable[0]["Value"].toFixed(3), ", P = ", coeffTable[0]["p-value"].toFixed(3), "
");
                      $("#result").append("Slope =  ", coeffTable[1]["Value"].toFixed(3), ", P = ", coeffTable[1]["p-value"].toFixed(3), "
");
                      $("#result").append("AIC for model = ", modelTable[0]["AIC"].toFixed(3), "
");
                      $("#result").append("lnL = ", modelTable[0]["loglik"].toFixed(3), "
");
                  }, this));

                } else if (result.status === 'FAILURE') {
                    $("#analyze").removeAttr("disabled");
                    $("#notice").text("Analysis failed. " + result.message);
                } else {
                    setTimeout(_.bind(this.checkResult, this), 1000);
                }
            }, this));
        };

        });

        $("#help").click(function() {
            $("#upload").popover({
                title: 'Step #1',
                content: 'Upload your table (csv or tsv) and tree (newick) here',
                placement: 'bottom',
                trigger: 'manual'
            });
            $("#upload").popover('toggle');
            $("#column-input-y").popover({
                title: 'Step #2',
                content: 'Drag your column of interest here',
                placement: 'left',
                trigger: 'manual'
            });
            $("#column-input-y").popover('toggle');
            $("#analyze").popover({
                title: 'Step #3',
                content: 'Click on the "Go!" button',
                placement: 'bottom',
                trigger: 'manual'
            });
            $("#analyze").popover('toggle');

        });

        $("#table-preview").click(function() {
            toggleInputTablePreview();
        });

        app.render();
    });
}(window.flow, window.$, window.girder));
<commit_msg>renaming variables<commit_after>/*jslint browser: true, nomen: true */

(function (flow, $, girder) {
    'use strict';

    $(document).ready(function () {
        girder.apiRoot = '/girder/api/v1';
        var app = new flow.App({
            el: 'body'
        });

        // Lookup the ID of the analysis that we wish to perform.
        app.analysisName = "PGLS_2traits-app";
        girder.restRequest({
            path: 'resource/search',
            data: {
                q: app.analysisName,
                types: JSON.stringify(["item"])
            }
        }).done(function (results) {
            app.analysisId = results["item"][0]._id;
            app.readyToAnalyze();
        });

        app.readyToAnalyze = function () {
            if ("column_x" in this && "column_y" in this && "table" in this && "tree" in this &&
                "analysisId" in this) {
                d3.select("#analyze").classed('disabled', false);
            }
        };

        function toggleInputTablePreview() {
            if ($("#table-preview-icon").hasClass("glyphicon-folder-close")) {
                $("#table-preview-icon").removeClass("glyphicon-folder-close");
                $("#table-preview-icon").addClass("glyphicon-folder-open");
                $("#table-preview-text").text(" Hide input table preview");
            }
            else {
                $("#table-preview-icon").removeClass("glyphicon-folder-open");
                $("#table-preview-icon").addClass("glyphicon-folder-close");
                $("#table-preview-text").text(" Show input table preview");
            }

            $("#input-table-vis").toggle('slow');
        }

        // override upload function for simple mode
        flow.DatasetManagementView.prototype.upload = function (file) {
            var reader = new FileReader();

            reader.onload = _.bind(function (e) {
                var dataset = {
                        name: file.name,
                        data: e.target.result
                    },
                    extension = file.name.split('.'),
                    typeFormat;

                extension = extension[extension.length - 1];
                typeFormat = flow.getTypeFormatsFromExtension(extension)[0];
                typeFormat = {type: typeFormat.type, format: typeFormat.format};
                _.extend(dataset, typeFormat);
                dataset = new Backbone.Model(dataset);

                // modifications for simple app begin here
                // if its a table, get the column names
                if (typeFormat.type == "table") {
                    app.table = dataset.get('data');
                    app.tableFormat = typeFormat.format;
                    d3.select("#table-name").html('Table: ' + file.name + ' ');
                    $("#column-input").text("Parsing column names...");
                    $("#column-names").empty();
                    flow.retrieveDatasetAsFormat(dataset, "table", "column.names", false, _.bind(function (error, dataset) {
                        var columnNames = dataset.get('data');
                        for (var i = 0; i < columnNames.length; ++i) {
                            // create drag-and-drop elements here
                            $("#column-names").append('
' + columnNames[i] + '
');
                        }
                        $(".draggable").draggable({
                             zIndex: 1, helper: "clone"
                        });
                        d3.select("#column-input").html('Drag column of interest here ');
                    }, this));

                    flow.retrieveDatasetAsFormat(dataset, "table", "rows", false, _.bind(function (error, dataset) {
                      // show the input table to help the user understand if their data
                      // was parsed correctly or not
                      var rowData = dataset.get('data');
                      rowData.rows = rowData.rows.slice(0, 3);
                      d3.select("#input-table-vis-container").classed('hidden', false);
                      $("#input-table-vis").table({ data: rowData });
                      d3.select("#column-input-y").html('Drag response variable (Y) here ');
                      d3.select("#column-input-x").html('Drag predictor variable (X) here ');
                    }, this));

                }

                else if (typeFormat.type == "tree") {
                    app.tree = dataset.get('data');
                    d3.select("#tree-name").html('Tree: ' + file.name + ' ');
                }
                app.readyToAnalyze();

                this.datasets.off('add', null, 'set-collection').add(dataset);
            }, this);

            reader.readAsText(file);
        };

        $("#column-input-y").droppable({
            drop: function( event, ui ) {
                var COI = ui.draggable.text();
                app.column_y = COI;
                d3.select("#column-input-y")
                    .classed('btn-primary', true)
                    .classed('btn-success', false)
                    .classed('bg-warning', false)
                    .html(COI + ' ' + " (Y) ~");
                app.readyToAnalyze();
            },
            over: function (event, ui) {
                d3.select("#column-input-y")
                    .classed('btn-success', true)
                    .classed('bg-warning', false);
            },
            out: function (event, ui) {
                d3.select("#column-input-y")
                    .classed('btn-success', false)
                    .classed('bg-warning', true);
            }
            });

            $("#column-input-x").droppable({
                drop: function( event, ui ) {
                    var COI = ui.draggable.text();
                    app.column_x = COI;
                    d3.select("#column-input-x")
                        .classed('btn-primary', true)
                        .classed('btn-success', false)
                        .classed('bg-warning', false)
                        .html(COI + ' ' + " (X)");
                    app.readyToAnalyze();
                },
                over: function (event, ui) {
                    d3.select("#column-input-x")
                        .classed('btn-success', true)
                        .classed('bg-warning', false);
                },
                out: function (event, ui) {
                    d3.select("#column-input-x")
                        .classed('btn-success', false)
                        .classed('bg-warning', true);
                }
                });

        function toggleCorrelationModel() {

                  if(document.getElementById("first_toggle").checked)
                  {
                    app.correlation="BM";
                  }
                  if(document.getElementById("second_toggle").checked)
                  {
                    app.correlation="OU";
                  }
                  if(document.getElementById("third_toggle").checked)
                  {
                    app.correlation="lambda";
                  }
        }

        $("#analyze").click(function() {
            $("#analyze").attr("disabled", "disabled");
            $("#analyze").text("Re-run");
            $("#notice").text("Performing analysis...");

            toggleCorrelationModel();

            var inputs = {
                dat:  {type: "table",  format: app.tableFormat,    data: app.table},
                tree:   {type: "tree",   format: "newick",           data: app.tree},
                dep_variable: {type: "string", format: "text",             data: app.column_y},
                ind_variable: {type: "string", format: "text",             data: app.column_x},
                model: {type: "string", format: "text",             data: app.correlation}
            };

            var outputs = {
				        coefficients: {type: "table", format: "rows"},
                pglsPlot: {type: "image", format: "png.base64"},
                modelfit_summary: {type: "table", format: "rows"}
            };

            flow.performAnalysis(app.analysisId, inputs, outputs,
                _.bind(function (error, result) {
                    app.taskId = result._id;
                    setTimeout(_.bind(app.checkResult, app), 1000);
                }, app));

        app.checkResult = function () {
            var check_url = '/item/' + this.analysisId + '/flow/' + this.taskId + '/status'
            girder.restRequest({path: check_url}).done(_.bind(function (result) {
                console.log(result.status);
                if (result.status === 'SUCCESS') {
                    // get result data
                    var result_url = '/item/' + this.ASRId + '/flow/' + this.taskId + '/result'
                    girder.restRequest({path: result_url}).done(_.bind(function (data) {
                        app.modelPlot = data.result.pglsPlot.data;
                      // render tree plot
                      $("#model-plot").image({ data: app.modelPlot });
                      $("#analyze").removeAttr("disabled");
                      $("#notice").text("Analysis succeeded!");
                      $('html, body').animate({
                          scrollTop: $("#model-plot").offset().top
                      }, 1000);

                      var coeffTable = data.result.coefficients.data.rows;
                      var modelTable = data.result.modelfit_summary.data.rows;
                      console.log(modelTable);

                      // pretty results
                      $("#result").append("
Results:<\h2>");
                      $("#result").append("Equation fit:
");
                      $("#result").append(app.column_y," = ", app.column_x, "

");
                      $("#result").append("Model for residuals: ", app.correlation, "

");
                      if(app.correlation == "OU")
                        $("#result").append("alpha = ", coeffTable[2]["Value"].toFixed(3));
                      $("#result").append("
Coefficients:<\h3>
");
                      $("#result").append("Intercept =  ", coeffTable[0]["Value"].toFixed(3), ", P = ", coeffTable[0]["p-value"].toFixed(3), "
");
                      $("#result").append("Slope =  ", coeffTable[1]["Value"].toFixed(3), ", P = ", coeffTable[1]["p-value"].toFixed(3), "
");
                      $("#result").append("AIC for model = ", modelTable[0]["AIC"].toFixed(3), "
");
                      $("#result").append("lnL = ", modelTable[0]["loglik"].toFixed(3), "
");
                  }, this));

                } else if (result.status === 'FAILURE') {
                    $("#analyze").removeAttr("disabled");
                    $("#notice").text("Analysis failed. " + result.message);
                } else {
                    setTimeout(_.bind(this.checkResult, this), 1000);
                }
            }, this));
        };

        });

        $("#help").click(function() {
            $("#upload").popover({
                title: 'Step #1',
                content: 'Upload your table (csv or tsv) and tree (newick) here',
                placement: 'bottom',
                trigger: 'manual'
            });
            $("#upload").popover('toggle');
            $("#column-input-y").popover({
                title: 'Step #2',
                content: 'Drag your column of interest here',
                placement: 'left',
                trigger: 'manual'
            });
            $("#column-input-y").popover('toggle');
            $("#analyze").popover({
                title: 'Step #3',
                content: 'Click on the "Go!" button',
                placement: 'bottom',
                trigger: 'manual'
            });
            $("#analyze").popover('toggle');

        });

        $("#table-preview").click(function() {
            toggleInputTablePreview();
        });

        app.render();
    });
}(window.flow, window.$, window.girder));
<|endoftext|>


<commit_before>const stylelint = require('stylelint')

const ruleName = 'primer/no-override'
const CLASS_PATTERN = /(\.[-\w]+)/g

let availableBundles = []
try {
  const meta = require('@primer/css/dist/meta.json')
  availableBundles = Object.keys(meta.bundles)
} catch (error) {
  throw new Error(
    `[${ruleName}] Unable to require('@primer/css/dist/meta.json')! Did you install it as a peerDependency?`
  )
}

const messages = stylelint.utils.ruleMessages(ruleName, {
  rejected: selector => `The class selector "${selector}" is immutable.`
})

module.exports = stylelint.createPlugin(ruleName, (enabled, options = {}) => {
  const {bundles = ['utilities']} = options

  const immutableSelectors = new Set()
  for (const bundle of bundles) {
    if (!availableBundles.includes(bundle)) {
      throw new Error(`Unknown @primer/css bundle: "${bundle}"!`)
    }
    const {cssstats} = require(`@primer/css/dist/${bundle}`)
    for (const selector of cssstats.selectors.values) {
      for (const classSelector of getClassSelectors(selector)) {
        immutableSelectors.add(classSelector)
      }
    }
  }

  // console.warn(`Got ${immutableSelectors.size} immutable selectors from: "${bundles.join('", "')}"`)

  return (root, result) => {
    const validOptions = stylelint.utils.validateOptions(result, ruleName, {
      actual: enabled,
      possible: [true, false]
    })

    if (!validOptions) {
      return
    }

    root.walkRules(rule => {
      for (const classSelector of getClassSelectors(rule.selector)) {
        if (immutableSelectors.has(classSelector)) {
          stylelint.utils.report({
            message: messages.rejected(classSelector),
            node: rule,
            result,
            ruleName
          })
        }
      }
    })
  }
})

module.exports.ruleName = ruleName
module.exports.messages = messages

function getClassSelectors(selector) {
  const match = selector.match(CLASS_PATTERN)
  return match ? [...match] : []
}
<commit_msg>fix(no-override): match entire selectors, simplify<commit_after>const stylelint = require('stylelint')

const ruleName = 'primer/no-override'
const CLASS_PATTERN = /(\.[-\w]+)/g

let primerMeta = {}
let availableBundles = []
try {
  primerMeta = require('@primer/css/dist/meta.json')
} catch (error) {
  throw new Error(
    `[${ruleName}] Unable to require('@primer/css/dist/meta.json')! Did you install it as a peerDependency?`
  )
}

availableBundles = Object.keys(primerMeta.bundles)

const messages = stylelint.utils.ruleMessages(ruleName, {
  rejected: selector => `The selector "${selector}" should not be overridden.`
})

module.exports = stylelint.createPlugin(ruleName, (enabled, options = {}) => {
  const {bundles = ['utilities']} = options

  const immutableSelectors = new Set()
  const immutableClassSelectors = new Set()
  for (const bundle of bundles) {
    if (!availableBundles.includes(bundle)) {
      throw new Error(`Unknown @primer/css bundle: "${bundle}"!`)
    }
    const {cssstats} = require(`@primer/css/dist/${bundle}`)
    for (const selector of cssstats.selectors.values) {
      immutableSelectors.add(selector)
      for (const classSelector of getClassSelectors(selector)) {
        immutableClassSelectors.add(classSelector)
      }
    }
  }

  // console.warn(`Got ${immutableSelectors.size} immutable selectors from: "${bundles.join('", "')}"`)

  return (root, result) => {
    const validOptions = stylelint.utils.validateOptions(result, ruleName, {
      actual: enabled,
      possible: [true, false]
    })

    if (!validOptions) {
      return
    }

    const report = (rule, selector) => stylelint.utils.report({
      message: messages.rejected(selector),
      node: rule,
      result,
      ruleName
    })

    root.walkRules(rule => {
      if (immutableSelectors.has(rule.selector)) {
        report(rule, rule.selector)
      } else {
        for (const classSelector of getClassSelectors(rule.selector)) {
          if (immutableClassSelectors.has(classSelector)) {
            report(rule, classSelector)
          }
        }
      }
    })
  }
})

function getClassSelectors(selector) {
  const match = selector.match(CLASS_PATTERN)
  return match ? [...match] : []
}
<|endoftext|>


<commit_before>import aganderSrc from '../assets/img/portfolio/thumbs/agander.jpg';
import broccoliSrc from '../assets/img/portfolio/thumbs/broccoli.png';
import jtSrc from '../assets/img/portfolio/thumbs/jt.jpg';
import pypesSrc from '../assets/img/portfolio/thumbs/pypes.png';
import spectrumSrc from '../assets/img/portfolio/thumbs/spectrum.png';
import splitSrc from '../assets/img/portfolio/thumbs/split.png';
import typeSrc from '../assets/img/portfolio/thumbs/type.png';
import vicesSrc from '../assets/img/portfolio/thumbs/vices.png';
import guesstimateSrc from '../assets/img/portfolio/thumbs/guesstimate.jpg';
import websiteSrc from '../assets/img/portfolio/thumbs/website.png';

export default [
    {
        name: 'This website',
        snippet: 'A progressively enhancing static site with offline caching and a unique content version control system',
        link: '/portfolio/website/',
        thumb: websiteSrc
    },
    {
        name: 'Guesstimate',
        snippet: 'Break your project up into easier to estimate chunks and total it for more accurate estimations',
        link: '/portfolio/guesstimate/',
        thumb: guesstimateSrc
    },
    {
        name: 'Spectrum',
        snippet: 'Spectrum is a web-based editor for writing software specification documents.',
        link: '/portfolio/spectrum/',
        thumb: spectrumSrc
    },
    {
        name: 'Agander',
        snippet: 'A productivity app aggregating calendar and tasks. Reduce the noise in your daily agenda.',
        link: '/portfolio/agander/',
        thumb: aganderSrc
    },
    {
        name: 'Split Visualiser',
        snippet: 'A web-app for easily visualising and sharing the muscle engagement of your exercise routine.',
        link: '/portfolio/split-visualiser/',
        thumb: splitSrc
    },
    {
        name: 'Journey Tree',
        snippet: 'A multi-platform collection of social networking and business applications for childcare staff and parents.',
        link: '/portfolio/journey-tree/',
        thumb: jtSrc
    },
    {
        name: 'Type With Apps',
        snippet: 'A web-app for easily visualising and sharing the muscle engagement of your exercise routine.',
        link: '/portfolio/type-with-apps/',
        thumb: typeSrc
    },
    // {
    //     name: 'Broccoli and Co.',
    //     snippet: 'A case study about the scalability and organisation of SPAs made in Angular 1.5 with comprehensive testing.',
    //     link: '/portfolio/broccoli-and-co/',
    //     thumb: broccoliSrc
    // },
    {
        name: 'Pypes',
        snippet: 'A micro-blogging platform with a RESTful interface and an Angular admin panel.',
        link: '/portfolio/pypes/',
        thumb: pypesSrc
    },
    {
        name: 'Vices',
        snippet: 'A micro-application designed to tell you how much money you\'re wasting on your bad habit.',
        link: '/portfolio/vices/',
        thumb: vicesSrc
    }
];<commit_msg>refactor: use portfolio name constants<commit_after>import aganderSrc from '../assets/img/portfolio/thumbs/agander.jpg';
import broccoliSrc from '../assets/img/portfolio/thumbs/broccoli.png';
import jtSrc from '../assets/img/portfolio/thumbs/jt.jpg';
import pypesSrc from '../assets/img/portfolio/thumbs/pypes.png';
import spectrumSrc from '../assets/img/portfolio/thumbs/spectrum.png';
import splitSrc from '../assets/img/portfolio/thumbs/split.png';
import typeSrc from '../assets/img/portfolio/thumbs/type.png';
import vicesSrc from '../assets/img/portfolio/thumbs/vices.png';
import guesstimateSrc from '../assets/img/portfolio/thumbs/guesstimate.jpg';
import websiteSrc from '../assets/img/portfolio/thumbs/website.png';
import {PORTFOLIO_ITEM_NAMES} from "constants";

export default [
    {
        name: PORTFOLIO_ITEM_NAMES.THIS_WEBSITE,
        snippet: 'A progressively enhancing static site with offline caching and a unique content version control system',
        link: '/portfolio/website/',
        thumb: websiteSrc
    },
    {
        name: PORTFOLIO_ITEM_NAMES.GUESSTIMATE,
        snippet: 'Break your project up into easier to estimate chunks and total it for more accurate estimations',
        link: '/portfolio/guesstimate/',
        thumb: guesstimateSrc
    },
    {
        name: PORTFOLIO_ITEM_NAMES.SPECTRUM,
        snippet: 'Spectrum is a web-based editor for writing software specification documents.',
        link: '/portfolio/spectrum/',
        thumb: spectrumSrc
    },
    {
        name: PORTFOLIO_ITEM_NAMES.AGANDER,
        snippet: 'A productivity app aggregating calendar and tasks. Reduce the noise in your daily agenda.',
        link: '/portfolio/agander/',
        thumb: aganderSrc
    },
    {
        name: PORTFOLIO_ITEM_NAMES.SPLIT_VISUALISER,
        snippet: 'A web-app for easily visualising and sharing the muscle engagement of your exercise routine.',
        link: '/portfolio/split-visualiser/',
        thumb: splitSrc
    },
    {
        name: PORTFOLIO_ITEM_NAMES.JOURNEY_TREE,
        snippet: 'A multi-platform collection of social networking and business applications for childcare staff and parents.',
        link: '/portfolio/journey-tree/',
        thumb: jtSrc
    },
    {
        name: PORTFOLIO_ITEM_NAMES.TYPE_WITH_APPS,
        snippet: 'A web-app for easily visualising and sharing the muscle engagement of your exercise routine.',
        link: '/portfolio/type-with-apps/',
        thumb: typeSrc
    },
    // {
    //     name: PORTFOLIO_ITEM_NAMES.BROCCOLI,
    //     snippet: 'A case study about the scalability and organisation of SPAs made in Angular 1.5 with comprehensive testing.',
    //     link: '/portfolio/broccoli-and-co/',
    //     thumb: broccoliSrc
    // },
    {
        name: PORTFOLIO_ITEM_NAMES.PYPES,
        snippet: 'A micro-blogging platform with a RESTful interface and an Angular admin panel.',
        link: '/portfolio/pypes/',
        thumb: pypesSrc
    },
    {
        name: PORTFOLIO_ITEM_NAMES.VICES,
        snippet: 'A micro-application designed to tell you how much money you\'re wasting on your bad habit.',
        link: '/portfolio/vices/',
        thumb: vicesSrc
    }
];<|endoftext|>