<commit_before>import React, {Component} from 'react';
import UpdateForm from '../Form/UpdateForm';
import moment from 'moment';
import API from "../../utils/API";
// import { RIEToggle, RIEInput, RIETextArea, RIENumber, RIETags, RIESelect } from 'riek';
// import _ from 'lodash';

// Title: This Book's Title  |E|
// Author: This Book's Author |E|
// Rating: This Book's Rating |E|

// When the user clicks |E|, change the text to an input field that holds the text. when enter is pushed, change the value of the state.

// have a flipper for each editable field.
// so {!titleEditMode && {this.state.title}}
// and {titleEditMode && <input blah={blah}> </>}

class Modal extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
      text: props.text,
      handleInputChange: props.handleInputChange,
      title: props.selectedBook.title,
      category: props.category,
      submit: props.submit,
      loadBooks: props.loadBooks,
      wantToRead: props.wantToRead,
      flipFavorite: props.flipFavorite,
      showModal: props.showModal,
      flipModal: props.flipModal,
      selectedBook: props.selectedBook,
      deleteBook: props.deleteBook,
      updateBook: props.updateBook,
      updateModalBook: props.updateModalBook,
      selectedTitle: props.selectedTitle,
      selectedAuthor: props.selectedAuthor,
      titleEditMode: false,
      authorEditMode: false,
      ratingEditMode: false,
      favoriteEditMode: false,
      noteEditMode: false,
      dateEditMode: false
    }
  }

  updateBook = (id, book) => {
        console.log("updateBook title is " + book.title + " BEFORE assignment");
        console.log("updateBook author is " + book.author + " BEFORE assignment");
        console.log("updateBook rating is " + book.rating + " BEFORE assignment");
        console.log("updateBook favorite is " + book.favorite + " BEFORE assignment");
        console.log("updateBook note is " + book.note + " BEFORE assignment");
        console.log("updateBook date is " + book.date + " BEFORE assignment");
        book.author = this.state.selectedAuthor
        book.title = this.state.selectedTitle
        book.rating = this.state.selectedRating
        book.favorite = this.state.favorite
        book.note = this.state.note
        book.date = this.state.date
        console.log("updateBook title is " + book.title + " AFTER assignment");
        console.log("updateBook author is " + book.author + " AFTER assignment");
        console.log("updateBook rating is " + book.rating + " AFTER assignment");
        console.log("updateBook favorite is " + book.favorite + " AFTER assignment");
        console.log("updateBook note is " + book.note + " AFTER assignment");
        console.log("updateBook date is " + book.date + " AFTER assignment");

        this.state.flipModal();

        API.updateBook(id, book)
        .then(res => this.state.loadBooks())
        .catch(err => console.log(err));

      }

  handleInputChange = event => {

    const { name, value } = event.target;

    this.setState({
      [name]: value
    });

  };

  render() {
    return(

 this.state.flipModal()}
        >

Book Details

            <button
              className="delete"
              aria-label="close"
              onClick={() => this.state.flipModal()}
            >
            </button>

              Title:
              {this.state.selectedBook.title}
              {/* {console.log("selectedBook title is " + this.state.selectedBook.title)} */}

              Author:
              {
                this.state.authorEditMode
                  ?
                    <form>
                      <input
                        className="input"
                        type="text"
                        name="selectedAuthor"
                        value={this.state.selectedAuthor}
                        onChange={this.handleInputChange}
                      />
                    </form>
                  : this.state.selectedAuthor
              }
              <button
                onClick={() => this.setState({authorEditMode:true})}
              >

              </button>

            {/*
Category: {this.state.selectedBook.category}
 */}

              Favorite? {this.state.selectedBook.favorite===true ? "Yes" : "No"}

            {/*

              Want to Read? {this.state.selectedBook.wantToRead}

 */}

              Rating:
              {this.state.selectedBook.rating}

              Notes:
              {this.state.selectedBook.note}

              Date Added:
              {moment(this.state.selectedBook.dateCompleted).format("MMMM Do, YYYY")}

            <button
              className="button is-success"
              onClick={(id, book) => this.updateBook(this.state.selectedBook.id, this.state.selectedBook)}
            >
              Save changes
            </button>
            <button
              className="button is-danger"
              //onClick={() => this.state.deleteBook(this.state.selectedBook.id)}
              onClick={() => {window.confirm('Are you sure you want to delete this book?') && this.state.deleteBook(this.state.selectedBook.id)}}
            >
              Delete
            </button>

    );

  }

}

export default Modal;<commit_msg>edit mode on title and note modal fields<commit_after>import React, {Component} from 'react';
import UpdateForm from '../Form/UpdateForm';
import moment from 'moment';
import API from "../../utils/API";
// import { RIEToggle, RIEInput, RIETextArea, RIENumber, RIETags, RIESelect } from 'riek';
// import _ from 'lodash';

// Title: This Book's Title  |E|
// Author: This Book's Author |E|
// Rating: This Book's Rating |E|

// When the user clicks |E|, change the text to an input field that holds the text. when enter is pushed, change the value of the state.

// have a flipper for each editable field.
// so {!titleEditMode && {this.state.title}}
// and {titleEditMode && <input blah={blah}> </>}

class Modal extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
      text: props.text,
      handleInputChange: props.handleInputChange,
      title: props.selectedBook.title,
      category: props.category,
      submit: props.submit,
      loadBooks: props.loadBooks,
      wantToRead: props.wantToRead,
      flipFavorite: props.flipFavorite,
      showModal: props.showModal,
      flipModal: props.flipModal,
      selectedBook: props.selectedBook,
      deleteBook: props.deleteBook,
      updateBook: props.updateBook,
      updateModalBook: props.updateModalBook,
      selectedTitle: props.selectedTitle,
      selectedAuthor: props.selectedAuthor,
      selectedNote: props.selectedNote,
      titleEditMode: false,
      authorEditMode: false,
      ratingEditMode: false,
      favoriteEditMode: false,
      noteEditMode: false,
      dateEditMode: false
    }
  }

  updateBook = (id, book) => {
        console.log("updateBook title is " + book.title + " BEFORE assignment");
        console.log("updateBook author is " + book.author + " BEFORE assignment");
        console.log("updateBook rating is " + book.rating + " BEFORE assignment");
        console.log("updateBook favorite is " + book.favorite + " BEFORE assignment");
        console.log("updateBook note is " + book.note + " BEFORE assignment");
        console.log("updateBook date is " + book.date + " BEFORE assignment");
        book.author = this.state.selectedAuthor
        book.title = this.state.selectedTitle
        book.rating = this.state.selectedRating
        book.favorite = this.state.favorite
        book.note = this.state.selectedNote
        book.date = this.state.date
        console.log("updateBook title is " + book.title + " AFTER assignment");
        console.log("updateBook author is " + book.author + " AFTER assignment");
        console.log("updateBook rating is " + book.rating + " AFTER assignment");
        console.log("updateBook favorite is " + book.favorite + " AFTER assignment");
        console.log("updateBook note is " + book.note + " AFTER assignment");
        console.log("updateBook date is " + book.date + " AFTER assignment");

        this.state.flipModal();

        API.updateBook(id, book)
        .then(res => this.state.loadBooks())
        .catch(err => console.log(err));

      }

  handleInputChange = event => {

    const { name, value } = event.target;

    this.setState({
      [name]: value
    });

  };

  render() {
    return(

 this.state.flipModal()}
        >

Book Details

            <button
              className="delete"
              aria-label="close"
              onClick={() => this.state.flipModal()}
            >
            </button>

          {/* Editable Fields */}

            {/* Title Field */}

              Title:
              {
                this.state.titleEditMode
                  ?
                    <form>
                      <input
                        className="input"
                        type="text"
                        name="selectedTitle"
                        value={this.state.selectedTitle}
                        onChange={this.handleInputChange}
                      />
                    </form>
                  : this.state.selectedTitle
              }
              <button
                onClick={() => this.setState({titleEditMode:true})}
              >

              </button>

            {/* Author Field */}

              Author:
              {
                this.state.authorEditMode
                  ?
                    <form>
                      <input
                        className="input"
                        type="text"
                        name="selectedAuthor"
                        value={this.state.selectedAuthor}
                        onChange={this.handleInputChange}
                      />
                    </form>
                  : this.state.selectedAuthor
              }
              <button
                onClick={() => this.setState({authorEditMode:true})}
              >

              </button>

            {/* Favorite Field */}

              Favorite? {this.state.selectedBook.favorite===true ? "Yes" : "No"}

              Rating:
              {this.state.selectedBook.rating}

            {/* Notes Field */}

              Notes:
              {
                this.state.noteEditMode
                  ?
                    <form>
                      <textarea
                        className="textarea"
                        type="text"
                        name="selectedNote"
                        value={this.state.selectedNote}
                        onChange={this.handleInputChange}
                      />
                    </form>
                  : this.state.selectedNote
              }
              <button
                onClick={() => this.setState({noteEditMode:true})}
              >

              </button>

            {/* Date Field */}

              Date Added:
              {moment(this.state.selectedBook.dateCompleted).format("MMMM Do, YYYY")}

            <button
              className="button is-success"
              onClick={(id, book) => this.updateBook(this.state.selectedBook.id, this.state.selectedBook)}
            >
              Save changes
            </button>
            <button
              className="button is-danger"
              //onClick={() => this.state.deleteBook(this.state.selectedBook.id)}
              onClick={() => {window.confirm('Are you sure you want to delete this book?') && this.state.deleteBook(this.state.selectedBook.id)}}
            >
              Delete
            </button>

    );

  }

}

export default Modal;<|endoftext|>


<commit_before>import expect from 'expect';
import usersReducer, { initialState } from '../../js/reducers/usersReducer';
import * as constants from '../../js/constants/AppConstants';

const getAction = (type, payload) => {
  return {
    type,
    ...payload
  };
};

describe('usersReducer', () => {
  const teams = [{
    id: 1,
    name: 'Team A'
  }, {
    id: 2,
    name: 'Team B'
  }];
  const user = { id: 1, name: 'User 1', teams };
  const user2 = { id: 2, name: 'User 2' };

  it('should return initial state on init', () => {
    expect(usersReducer(undefined, {})).toEqual(initialState);
  });

  it('should return initial state on unknown action', () => {
    expect(usersReducer(undefined, getAction('UNKNOWN_ACTION'))).toEqual(initialState);
  });

  it('should return an Object<User> indexed by ID with USER_LIST_SUCCESS action', () => {
    const action = getAction(constants.USER_LIST_SUCCESS, {
      users: [user]
    });

    expect(usersReducer(undefined, action)).toEqual({ 1: user });
  });

  it('should update user info on state when called with USER_GET_SUCCESS or USER_UPDATE_SUCCESS', () => {
    const state = { 1: user, 2: user2 };
    const updatedUser = { id: 1, name: 'User Updated', teams };
    const actionPayload = { user: updatedUser };
    const actionGetSuccess = getAction(constants.USER_GET_SUCCESS, actionPayload);
    const actionUpdateSuccess = getAction(constants.USER_UPDATE_SUCCESS, actionPayload);
    const expected = { 1: updatedUser, 2: user2 };

    expect(usersReducer(state, actionGetSuccess)).toEqual(expected);
    expect(Object.keys(usersReducer(state, actionGetSuccess)).length).toBe(2);

    expect(usersReducer(state, actionUpdateSuccess)).toEqual(expected);
    expect(Object.keys(usersReducer(state, actionUpdateSuccess)).length).toBe(2);
  });

  it('should assign "isAdmin: true" property to an user when called with USER_GRANT_ADMIN_SUCCESS action', () => {
    const state = { 1: user };
    const action = getAction(constants.USER_GRANT_ADMIN_SUCCESS, { id: 1 });

    expect(usersReducer(state, action)).toEqual({
      1: {...user, isAdmin: true }
    });
  });

  it('should assign "isAdmin: false" property to an user when called with USER_REVOKE_ADMIN_SUCCESS action', () => {
    const state = { 1: user };
    const action = getAction(constants.USER_REVOKE_ADMIN_SUCCESS, { id: 1 });

    expect(usersReducer(state, action)).toEqual({
      1: {...user, isAdmin: false }
    });
  });

  it('should delete user info on state when called with USER_GET_FAILURE or USER_DELETE_SUCCESS', () => {
    const state = { 1: user, 2: user2 };
    const actionPayload = {id: 1};
    const actionGetFailure = getAction(constants.USER_GET_FAILURE, actionPayload);
    const actionDeleteSuccess = getAction(constants.USER_DELETE_SUCCESS, actionPayload);
    const expected = { 2: user2 };

    expect(usersReducer(state, actionGetFailure)).toEqual(expected);
    expect(Object.keys(usersReducer(state, actionGetFailure)).length).toBe(1);

    expect(usersReducer(state, actionDeleteSuccess)).toEqual(expected);
    expect(Object.keys(usersReducer(state, actionDeleteSuccess)).length).toBe(1);
  });

  it('should return an empty object when called for APP_LOGIN_FAILURE, APP_LOGOUT and USER_LIST_FAILURE actions', () => {
    const expected = {};

    expect(usersReducer(undefined, getAction(constants.APP_LOGIN_FAILURE, {}))).toEqual(expected);
    expect(usersReducer(undefined, getAction(constants.APP_LOGOUT, {}))).toEqual(expected);
    expect(usersReducer(undefined, getAction(constants.USER_LIST_FAILURE, {}))).toEqual(expected);
  });

  it('should unlink a given Team ID from users teams object on TEAM_UNLINK_USER_SUCCESS action', () => {
    const state = {
      1: {
        ...user,
        teams: [{
          id: 2,
          name: 'X-Team'
        }]
      }
    };
    const payload = {
      userId: 1,
      id: 2
    };
    const expected = {
      1: {
        ...user,
        teams: []
      }
    };
    const result = getAction(constants.TEAM_UNLINK_USER_SUCCESS, payload);

    expect(usersReducer(state, result)).toEqual(expected);
    expect(usersReducer(state, result)[1].teams.length).toBe(0);
  });
});
<commit_msg>Update tests.<commit_after>import expect from 'expect';
import usersReducer, { initialState } from '../../js/reducers/usersReducer';
import * as constants from '../../js/constants/AppConstants';

const getAction = (type, payload) => {
  return {
    type,
    ...payload
  };
};

describe('usersReducer', () => {
  const teams = [{
    id: 1,
    name: 'Team A'
  }, {
    id: 2,
    name: 'Team B'
  }];
  const user = { id: 1, name: 'User 1', teams };
  const user2 = { id: 2, name: 'User 2' };

  it('should return initial state on init', () => {
    expect(usersReducer(undefined, {})).toEqual(initialState);
  });

  it('should return initial state on unknown action', () => {
    expect(usersReducer(undefined, getAction('UNKNOWN_ACTION'))).toEqual(initialState);
  });

  it('should return an Object<User> indexed by ID with USER_LIST_SUCCESS action', () => {
    const action = getAction(constants.USER_LIST_SUCCESS, {
      users: [user]
    });

    expect(usersReducer(undefined, action)).toEqual({
      1: user,
      visible: true
    });
  });

  it('should update user info on state when called with USER_GET_SUCCESS or USER_UPDATE_SUCCESS', () => {
    const state = { 1: user, 2: user2 };
    const updatedUser = { id: 1, name: 'User Updated', teams };
    const actionPayload = { user: updatedUser };
    const actionGetSuccess = getAction(constants.USER_GET_SUCCESS, actionPayload);
    const actionUpdateSuccess = getAction(constants.USER_UPDATE_SUCCESS, actionPayload);
    const expected = { 1: updatedUser, 2: user2 };

    expect(usersReducer(state, actionGetSuccess)).toEqual(expected);
    expect(Object.keys(usersReducer(state, actionGetSuccess)).length).toBe(2);

    expect(usersReducer(state, actionUpdateSuccess)).toEqual(expected);
    expect(Object.keys(usersReducer(state, actionUpdateSuccess)).length).toBe(2);
  });

  it('should assign "isAdmin: true" property to an user when called with USER_GRANT_ADMIN_SUCCESS action', () => {
    const state = { 1: user };
    const action = getAction(constants.USER_GRANT_ADMIN_SUCCESS, { id: 1 });

    expect(usersReducer(state, action)).toEqual({
      1: {...user, isAdmin: true }
    });
  });

  it('should assign "isAdmin: false" property to an user when called with USER_REVOKE_ADMIN_SUCCESS action', () => {
    const state = { 1: user };
    const action = getAction(constants.USER_REVOKE_ADMIN_SUCCESS, { id: 1 });

    expect(usersReducer(state, action)).toEqual({
      1: {...user, isAdmin: false }
    });
  });

  it('should delete user info on state when called with USER_GET_FAILURE or USER_DELETE_SUCCESS', () => {
    const state = { 1: user, 2: user2 };
    const actionPayload = {id: 1};
    const actionGetFailure = getAction(constants.USER_GET_FAILURE, actionPayload);
    const actionDeleteSuccess = getAction(constants.USER_DELETE_SUCCESS, actionPayload);
    const expected = {
      1: user,
      2: user2
    };

    expect(usersReducer(state, actionGetFailure)).toEqual(expected);
    expect(Object.keys(usersReducer(state, actionGetFailure)).length).toBe(2);

    expect(usersReducer(state, actionDeleteSuccess)).toEqual(expected);
    expect(Object.keys(usersReducer(state, actionDeleteSuccess)).length).toBe(2);
  });

  it('should return an empty object when called for APP_LOGIN_FAILURE, APP_LOGOUT and USER_LIST_FAILURE actions', () => {
    const expected = {
      visible: true
    };

    expect(usersReducer(undefined, getAction(constants.APP_LOGIN_FAILURE, {}))).toEqual(expected);
    expect(usersReducer(undefined, getAction(constants.APP_LOGOUT, {}))).toEqual(expected);
    expect(usersReducer(undefined, getAction(constants.USER_LIST_FAILURE, {}))).toEqual(expected);
  });

  it('should unlink a given Team ID from users teams object on TEAM_UNLINK_USER_SUCCESS action', () => {
    const state = {
      1: {
        ...user,
        teams: [{
          id: 2,
          name: 'X-Team'
        }]
      }
    };
    const payload = {
      userId: 1,
      id: 2
    };
    const expected = {
      1: {
        ...user,
        teams: []
      }
    };
    const result = getAction(constants.TEAM_UNLINK_USER_SUCCESS, payload);

    expect(usersReducer(state, result)).toEqual(expected);
    expect(usersReducer(state, result)[1].teams.length).toBe(0);
  });
});
<|endoftext|>


<commit_before>/*
 * The MIT License
 *
 * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi,
 * Daniel Dyer, Yahoo! Inc., Alan Harder, InfraDNA, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

function assertDocumentModeOK() {
    if (YAHOO.env.ua.ie && YAHOO.env.ua.ie !== document.documentMode) {
        setTimeout(function() {
            alert("WARNING: Your Internet Explorer appears to be set to a non-default 'Document Mode' (see Developer Tools - press F12).\n" +
                "\n" +
                "Jenkins may not display properly in this browser.");
        }, 1500);
    }
}

assertDocumentModeOK();
<commit_msg>EOL `msie.js` (#6574)<commit_after><|endoftext|>


<commit_before>var assert = require('chai').assert;
var Match = require('../src/Match');
var MatchOutputter = require('../src/MatchOutputter');
var common = require('./common');

describe('Match', function () {
    var match = new Match(common.matchParams);

    describe('#simulate()', function () {
        var result = match.simulate();
        var startTime = match.startTime.getTime();

        it('should return the same score as #score property', function () {
            assert.equal(result, match.score);
        });

        context('creating the first half', function () {
            it('should set its #startTime correctly', function () {
                assert.equal(match.firstHalf.startTime.getTime(), startTime);
            });

            it('should have a length of 45 minutes', function () {
                assert.equal(match.firstHalf.length, 45 * 60000);
            });
        });

        context('creating the second half', function () {
            it('should start 1 hour after the match started', function () {
                var expectedStartTime = startTime + (60 * 60000);
                var secondHalfStartTime = match.secondHalf.startTime.getTime();

                assert.equal(secondHalfStartTime, expectedStartTime);
            });

            it('should have a length of 45 minutes', function () {
                assert.equal(match.secondHalf.length, 45 * 60000);
            });
        });

        context('creating the first half of extra time', function () {
            it('should start 5 minutes after second half ended', function () {
                var secondHalfFinish = match.secondHalf.finishTime;
                var secondHalfFinishTime = secondHalfFinish.getTime();
                var expectedStartTime = secondHalfFinishTime + (5 * 60000);
                var thisStart = match.extraTimeFirstHalf.startTime;
                var thisStartTime = thisStart.getTime();

                assert.equal(thisStartTime, expectedStartTime);
            });

            it('should have a length of 15 minutes', function () {
                assert.equal(match.extraTimeFirstHalf.length, 15 * 60000);
            });
        });

        context('creating the second half of extra time', function () {
            it('should start 5 minutes after first half of ET', function () {
                var firstHalfETFinish = match.extraTimeFirstHalf.finishTime;
                var firstHalfETFinishTime = firstHalfETFinish.getTime();
                var secondHalfETStart = match.extraTimeSecondHalf.startTime;
                var secondHalfETStartTime = secondHalfETStart.getTime();
                var expectedStartTime = firstHalfETFinishTime + (5 * 60000);

                assert.equal(secondHalfETStartTime, expectedStartTime);
            });

            it('should have a length of 15 minutes', function () {
                var expectedLength = 15 * 60000;

                assert.equal(match.extraTimeSecondHalf.length, expectedLength);
            });
        });

        context('creating penalties', function () {
            it('should start 5 minutes after second half of ET', function () {
                var previous = match.extraTimeSecondHalf;
                var previousFinishTime = previous.finishTime.getTime();
                var expectedStartTime = previousFinishTime + (5 * 60000);
                var actualStartTime = match.penalties.startTime.getTime();

                assert.equal(actualStartTime, expectedStartTime);
            });
        });
    });

    describe('#getFinishTime', function () {
        var match = new Match(common.matchParams);

        context('#wentToExtraTime and #wentToPenalties are false', function () {
            match.wentToExtraTime = false;
            match.wentToPenalties = false;

            var finishTime = match.getFinishTime().getTime();

            it('should return second half finish time', function () {
                var expectedFinishTime = match.secondHalf.finishTime.getTime();

                assert.equal(finishTime, expectedFinishTime);
            });
        });

        context('#wentToExtraTime true, #wentToPenalties false', function () {
            match.wentToExtraTime = true;
            match.wentToPenalties = false;

            var finishTime = match.getFinishTime().getTime();

            it('should return second half ET finish time', function () {
                var expectedFinishTime = match.extraTimeSecondHalf
                    .finishTime
                    .getTime();

                assert.equal(finishTime, expectedFinishTime);
            });
        });

        context('#wentToExtraTime true, #wentToPenalties true', function () {
            match.wentToExtraTime = true;
            match.wentToPenalties = true;

            var finishTime = match.getFinishTime();

            it('should return penalties finish time', function () {
                var expectedFinishTime = match.penalties.finishTime;

                assert.equal(finishTime, expectedFinishTime);
            });
        });

        context('#wentToExtraTime false, #wentToPenalties true', function () {
            match.wentToExtraTime = false;
            match.wentToPenalties = true;

            var finishTime = match.getFinishTime();

            it('should return penalties finish time', function () {
                var expectedFinishTime = match.penalties.finishTime;

                assert.equal(finishTime, expectedFinishTime);
            });
        });
    });

    describe('#startTime', function () {
        var startTime = common.matchParams.startTime;

        it('should set the first half start time', function () {
            var firstHalfStartTime = match.firstHalf.startTime;

            assert.equal(firstHalfStartTime.getTime(), startTime.getTime());
        });

        it('should always set startTime as instance of Date', function () {
            delete common.matchParams.startTime;

            var match = new Match(common.matchParams);

            assert.instanceOf(match.startTime, Date);
        });
    });
});
<commit_msg>Tests whether finishTime is set in Match<commit_after>var assert = require('chai').assert;
var Match = require('../src/Match');
var MatchOutputter = require('../src/MatchOutputter');
var common = require('./common');

describe('Match', function () {
    var match = new Match(common.matchParams);

    describe('#simulate()', function () {
        var result = match.simulate();
        var startTime = match.startTime.getTime();

        it('should return the same score as #score property', function () {
            assert.equal(result, match.score);
        });

        context('creating the first half', function () {
            it('should set its #startTime correctly', function () {
                assert.equal(match.firstHalf.startTime.getTime(), startTime);
            });

            it('should have a length of 45 minutes', function () {
                assert.equal(match.firstHalf.length, 45 * 60000);
            });
        });

        context('creating the second half', function () {
            it('should start 1 hour after the match started', function () {
                var expectedStartTime = startTime + (60 * 60000);
                var secondHalfStartTime = match.secondHalf.startTime.getTime();

                assert.equal(secondHalfStartTime, expectedStartTime);
            });

            it('should have a length of 45 minutes', function () {
                assert.equal(match.secondHalf.length, 45 * 60000);
            });
        });

        context('creating the first half of extra time', function () {
            it('should start 5 minutes after second half ended', function () {
                var secondHalfFinish = match.secondHalf.finishTime;
                var secondHalfFinishTime = secondHalfFinish.getTime();
                var expectedStartTime = secondHalfFinishTime + (5 * 60000);
                var thisStart = match.extraTimeFirstHalf.startTime;
                var thisStartTime = thisStart.getTime();

                assert.equal(thisStartTime, expectedStartTime);
            });

            it('should have a length of 15 minutes', function () {
                assert.equal(match.extraTimeFirstHalf.length, 15 * 60000);
            });
        });

        context('creating the second half of extra time', function () {
            it('should start 5 minutes after first half of ET', function () {
                var firstHalfETFinish = match.extraTimeFirstHalf.finishTime;
                var firstHalfETFinishTime = firstHalfETFinish.getTime();
                var secondHalfETStart = match.extraTimeSecondHalf.startTime;
                var secondHalfETStartTime = secondHalfETStart.getTime();
                var expectedStartTime = firstHalfETFinishTime + (5 * 60000);

                assert.equal(secondHalfETStartTime, expectedStartTime);
            });

            it('should have a length of 15 minutes', function () {
                var expectedLength = 15 * 60000;

                assert.equal(match.extraTimeSecondHalf.length, expectedLength);
            });
        });

        context('creating penalties', function () {
            it('should start 5 minutes after second half of ET', function () {
                var previous = match.extraTimeSecondHalf;
                var previousFinishTime = previous.finishTime.getTime();
                var expectedStartTime = previousFinishTime + (5 * 60000);
                var actualStartTime = match.penalties.startTime.getTime();

                assert.equal(actualStartTime, expectedStartTime);
            });
        });

        context('sets #finishTime to return of #getFinishTime', function () {
            assert.equal(match.finishTime, match.getFinishTime());
        });
    });

    describe('#getFinishTime()', function () {
        var match = new Match(common.matchParams);

        context('#wentToExtraTime and #wentToPenalties are false', function () {
            match.wentToExtraTime = false;
            match.wentToPenalties = false;

            var finishTime = match.getFinishTime().getTime();

            it('should return second half finish time', function () {
                var expectedFinishTime = match.secondHalf.finishTime.getTime();

                assert.equal(finishTime, expectedFinishTime);
            });
        });

        context('#wentToExtraTime true, #wentToPenalties false', function () {
            match.wentToExtraTime = true;
            match.wentToPenalties = false;

            var finishTime = match.getFinishTime().getTime();

            it('should return second half ET finish time', function () {
                var expectedFinishTime = match.extraTimeSecondHalf
                    .finishTime
                    .getTime();

                assert.equal(finishTime, expectedFinishTime);
            });
        });

        context('#wentToExtraTime true, #wentToPenalties true', function () {
            match.wentToExtraTime = true;
            match.wentToPenalties = true;

            var finishTime = match.getFinishTime();

            it('should return penalties finish time', function () {
                var expectedFinishTime = match.penalties.finishTime;

                assert.equal(finishTime, expectedFinishTime);
            });
        });

        context('#wentToExtraTime false, #wentToPenalties true', function () {
            match.wentToExtraTime = false;
            match.wentToPenalties = true;

            var finishTime = match.getFinishTime();

            it('should return penalties finish time', function () {
                var expectedFinishTime = match.penalties.finishTime;

                assert.equal(finishTime, expectedFinishTime);
            });
        });
    });

    describe('#startTime', function () {
        var startTime = common.matchParams.startTime;

        it('should set the first half start time', function () {
            var firstHalfStartTime = match.firstHalf.startTime;

            assert.equal(firstHalfStartTime.getTime(), startTime.getTime());
        });

        it('should always set startTime as instance of Date', function () {
            delete common.matchParams.startTime;

            var match = new Match(common.matchParams);

            assert.instanceOf(match.startTime, Date);
        });
    });
});
<|endoftext|>


<commit_before>/**
 * .reel Unit Tests
 */
(function($){

  module('Animation', reel_test_module_routine);

  asyncTest( 'When at least one instance of Reel is present in the DOM a shared ticker is started', function()
  {
    expect(1);
    var
      ticks = 0;

    $(document).bind('tick.reel.test', function tick(){
      ok( false, 'Ticker should not be running');
      ticks++
    });

    setTimeout(function(){
      equal( ticks, 0, 'Ticker isn\'t running when no Reel is on');
      start();
    }, 100);
  });

  asyncTest( 'Ticker is driven by `leader`\'s data from `$.reel.leader()`', function()
  {
    expect(9);

    $(document).bind('tick.reel.test', tick);

    var
      ticks = 0,
      $faster = $('#image').reel({ tempo: 20 }),
      $slower = $('#image2').reel({ tempo: 10 });

    setTimeout(function(){
      deepEqual( $.reel.leader(), $faster.data(), 'Leader\'s data are the first (oldest living) instance\'s data')
      equals( $.reel.leader('tempo'), $faster.data('tempo'), 'Timer keeps faster tempo dictated by the leader');

      ok( $faster.unreel(), 'The older faster instance destroyed (the latter slower instance remains)');

      setTimeout(function(){
        deepEqual( $.reel.leader(), $slower.data(), 'Leader\'s data are the second (now the only) instance\'s data')
        equals( $.reel.leader('tempo'), $slower.data('tempo'), 'Ticker slowed down');

        ok( $slower.unreel(), 'Slower instance removed too (no instance remains)')
        var
          ticks_copy= ticks;

        setTimeout(function(){
          equals( $.reel.leader(), undefined, 'Without a leader there\'s no data');
          equals( $.reel.leader('tempo'), undefined, 'and no leader\'s tempo');
          equals( ticks_copy, ticks, 'Ticker is stopped.');

          start();
        }, 1000);

      }, 1000);

    }, 1000);

    function tick(){
      ticks++
    }
  });

  // We generate tests for several different tempos ranging from 6 to 48
  $.each([6, 8, 10, 12, 18, 24, 36], function(ix, tempo){

    var
      one_second= 1000,
      lazy_tempo= tempo / ($.reel.lazy? $.reel.def.laziness : 1),
      tolerate= 10 // percents

    // We also try both animated and non-animated
    $.each([0, 1], function(ixx, speed){

      asyncTest( 'Measuring 1 second timing accuracy when running ' + (speed ? 'animated' : 'non-animated') + ' instance at `tempo: ' + lazy_tempo + '`', function()
      {
        expect(1);

        var
          ticks= 0,
          sum= 0,
          bang= +new Date(),
          $reel= $('#image').reel({ tempo: tempo, speed: speed })

        $(document).bind('tick.reel.test', function tick(){
          ticks++;
        });

        setTimeout(function(duration){
          var
            duration= +new Date() - bang,
            excess= duration % one_second / 10

          ok( excess < tolerate, 'Yielded ' + ticks + ' ticks with ' + excess + ' % of measured overdue');
          start();
        }, one_second);
      });
    });
  });

  asyncTest( 'Running instances have their overall running cost (in ms) exposed as `$.reel.cost`', function()
  {
    expect(3);

    $('#image').reel({ speed: 1 });

    setTimeout(function(){
      var
        cost_of_one

      ok( is('Number', cost_of_one= $.reel.cost), 'Number `$.reel.cost`')
      ok( cost_of_one >= 0, 'Non-zero cost of one instance (' + cost_of_one + ' ms)' )

      $('#image2').reel({ speed: 2 });
      $('#stitched_looping').reel({ speed: 2 });

      setTimeout(function(){
        var
          cost_of_three= $.reel.cost

        ok( cost_of_three > 0, 'Non-zero cost of two more instances (' + cost_of_three + ' ms)' )
        start();

      }, 100);

    }, 100);

  });

  $.each({
    'no opening': { /* No `opening` equals `opening: 0` */ },
    'zero opening': { opening: 0 },
    'valid opening': { opening: 1.23 }
  },
  function(ix, setup){
    asyncTest( 'Removal of redundant `rowChange` and untimately the `frameChange` event from `loaded.fu` handler left the functionality untouched when ' + ix + ' is set', function()
    {
      expect(1);
      var
        ticked,
        $reel= $('#image').reel(setup)

      $(document).bind('loaded.test', function(){
        $(document).bind('frameChange.test', function(){
          ok( !ticked, '`openingDone` induced `frameChange` triggered before the first tick');
          start();
        })
        $(document).bind('tick.reel.test', function(){
          ticked= true;
        });
      });

    });
  });

})(jQuery);
<commit_msg>Shortened also the wating times for leader testing.<commit_after>/**
 * .reel Unit Tests
 */
(function($){

  module('Animation', reel_test_module_routine);

  asyncTest( 'When at least one instance of Reel is present in the DOM a shared ticker is started', function()
  {
    expect(1);
    var
      ticks = 0;

    $(document).bind('tick.reel.test', function tick(){
      ok( false, 'Ticker should not be running');
      ticks++
    });

    setTimeout(function(){
      equal( ticks, 0, 'Ticker isn\'t running when no Reel is on');
      start();
    }, 100);
  });

  asyncTest( 'Ticker is driven by `leader`\'s data from `$.reel.leader()`', function()
  {
    expect(9);

    $(document).bind('tick.reel.test', tick);

    var
      ticks = 0,
      $faster = $('#image').reel({ tempo: 20 }),
      $slower = $('#image2').reel({ tempo: 10 });

    setTimeout(function(){
      deepEqual( $.reel.leader(), $faster.data(), 'Leader\'s data are the first (oldest living) instance\'s data')
      equals( $.reel.leader('tempo'), $faster.data('tempo'), 'Timer keeps faster tempo dictated by the leader');

      ok( $faster.unreel(), 'The older faster instance destroyed (the latter slower instance remains)');

      setTimeout(function(){
        deepEqual( $.reel.leader(), $slower.data(), 'Leader\'s data are the second (now the only) instance\'s data')
        equals( $.reel.leader('tempo'), $slower.data('tempo'), 'Ticker slowed down');

        ok( $slower.unreel(), 'Slower instance removed too (no instance remains)')
        var
          ticks_copy= ticks;

        setTimeout(function(){
          equals( $.reel.leader(), undefined, 'Without a leader there\'s no data');
          equals( $.reel.leader('tempo'), undefined, 'and no leader\'s tempo');
          equals( ticks_copy, ticks, 'Ticker is stopped.');

          start();
        }, 100);

      }, 100);

    }, 100);

    function tick(){
      ticks++
    }
  });

  // We generate tests for several different tempos ranging from 6 to 48
  $.each([6, 8, 10, 12, 18, 24, 36], function(ix, tempo){

    var
      one_second= 1000,
      lazy_tempo= tempo / ($.reel.lazy? $.reel.def.laziness : 1),
      tolerate= 10 // percents

    // We also try both animated and non-animated
    $.each([0, 1], function(ixx, speed){

      asyncTest( 'Measuring 1 second timing accuracy when running ' + (speed ? 'animated' : 'non-animated') + ' instance at `tempo: ' + lazy_tempo + '`', function()
      {
        expect(1);

        var
          ticks= 0,
          sum= 0,
          bang= +new Date(),
          $reel= $('#image').reel({ tempo: tempo, speed: speed })

        $(document).bind('tick.reel.test', function tick(){
          ticks++;
        });

        setTimeout(function(duration){
          var
            duration= +new Date() - bang,
            excess= duration % one_second / 10

          ok( excess < tolerate, 'Yielded ' + ticks + ' ticks with ' + excess + ' % of measured overdue');
          start();
        }, one_second);
      });
    });
  });

  asyncTest( 'Running instances have their overall running cost (in ms) exposed as `$.reel.cost`', function()
  {
    expect(3);

    $('#image').reel({ speed: 1 });

    setTimeout(function(){
      var
        cost_of_one

      ok( is('Number', cost_of_one= $.reel.cost), 'Number `$.reel.cost`')
      ok( cost_of_one >= 0, 'Non-zero cost of one instance (' + cost_of_one + ' ms)' )

      $('#image2').reel({ speed: 2 });
      $('#stitched_looping').reel({ speed: 2 });

      setTimeout(function(){
        var
          cost_of_three= $.reel.cost

        ok( cost_of_three > 0, 'Non-zero cost of two more instances (' + cost_of_three + ' ms)' )
        start();

      }, 100);

    }, 100);

  });

  $.each({
    'no opening': { /* No `opening` equals `opening: 0` */ },
    'zero opening': { opening: 0 },
    'valid opening': { opening: 1.23 }
  },
  function(ix, setup){
    asyncTest( 'Removal of redundant `rowChange` and untimately the `frameChange` event from `loaded.fu` handler left the functionality untouched when ' + ix + ' is set', function()
    {
      expect(1);
      var
        ticked,
        $reel= $('#image').reel(setup)

      $(document).bind('loaded.test', function(){
        $(document).bind('frameChange.test', function(){
          ok( !ticked, '`openingDone` induced `frameChange` triggered before the first tick');
          start();
        })
        $(document).bind('tick.reel.test', function(){
          ticked= true;
        });
      });

    });
  });

})(jQuery);
<|endoftext|>


<commit_before>function Serial(dataCallback, connectCallback)
{
    var connected = false;                                  // whether or not a valid Quizmaster micro:bit is connected
    var CONNECTION_INFO = null;                             // holds the Chrome API serial connection info
    var serialBuffer = [];                                  // used to buffer data until we have a full commands
    chrome.serial.onReceive.addListener(onData);
    chrome.serial.onReceiveError.addListener(onError);

    /* Handles the buffering and parsing of any received data before passing it back to the main program */
    function onData(received)
    {
        var data = String.fromCharCode.apply(null, new Uint8Array(received.data));
        serialBuffer.push(data);
        // check if it's the end of the command
        if (data.lastIndexOf(";") > -1) {
            var response = serialBuffer.join("");
            var parsedResponse = response.split(/[;:]+/);
            parsedResponse.pop(); // remove the empty index
            if (!connected && parsedResponse[0] === "ack") {
              // only confirm a connection if the micro:bit acks the connect request ack
              // this means that only correctly flashed micro:bits can succesfully connect
              connected = true;
              connectCallback(connected);
            }
            dataCallback(parsedResponse);
            serialBuffer = [];
        }
    }

    /* Handles updating the connection state for common d/c errors */
    function onError(err) {
      if (!(err.error === "device_lost") && !(err.error === "disconnected") && !(err.error === "break"))
        throw new Error(err.error);
      connected = false;
      connectCallback(connected);
    }

    /* Convert given String to Uint8Array */
    function utf8ArrayBufFromStr(str)
    {
        var strUtf8 = unescape(encodeURIComponent(str));
        var arrayBuf = new Uint8Array(strUtf8.length);
        for (var i = 0; i < strUtf8.length; i++) {
            arrayBuf[i] = strUtf8.charCodeAt(i);
        }
        return arrayBuf;
    }

    /* Convert given Uint8Array to String */
    function strFromUtf8ArrayBuf(arrayBuf)
    {
        return escape(decodeURIComponent(String.fromCharCode.apply(null, arrayBuf)));
    }

    /* Attempts to write given string to the connected serial device */
    function write(str)
    {
        if (CONNECTION_INFO)
        {
          console.log(str);
            chrome.serial.send(CONNECTION_INFO.connectionId, utf8AbFromStr(str).buffer, function(info) { });
        }
    }

    /* Checks the connected serial devices for common micro:bit display names, if one matches, the callback provides the relevant port object (else it provides null) */
    function getMicrobitPort(callback) {
      chrome.serial.getDevices(function(portList) {
        for (var i = 0; i < portList.length; i++) {
          var port = portList[i];
          if ((port.displayName == 'mbed Serial Port') || ((port.displayName == 'MBED CMSIS_DAP') && (port.path.indexOf("tty") >= 0))) { // for windows and os x
              return callback(port);
          }
        }
        callback(null);
      });
    }

    /* Attempts to automatically find and connect to a microbit connected to the computer via serial
    /*    Callback provides a connected boolean (whether or not the connection was succesful) */
    function connect(callback) {
      getMicrobitPort(function(port) {
        if (port) {
          chrome.serial.connect(port.path, {bitrate: 115200}, function(connectionInfo) {
            if (chrome.runtime.lastError) {
              CONNECTION_INFO = null;
              connected = false;
              connectCallback(connected);
              console.log(chrome.runtime.lastError.message);
              return callback(connected);
            }
            else {
              // wait for micro:bit's ack response to ensure it's flashed correctly before confirming connection
              CONNECTION_INFO = connectionInfo;
              write("ack;");
              setTimeout(function() {
                if (!connected) {
                  // connected micro:bit isn't flashed with the correct program
                  callback(false);
                }
                else {
                  callback(true);
                }
              }, 5000);
            }
          });
        }
        else {
          // no micro:bit found
          connected = false;
          connectCallback(connected);
          callback(false);
        }
      });
    }

    // initial connection attempt
    connect(()=>{});

    // public methods
    return {
        "write": function(str)
        {
            write(str);
        },
        "isConnected": function() {
          return connected;
        },
        "reconnect": function(callback) {
          if (connected)
            return callback(true);
          connect(callback);
        }
    }

}

export default Serial
<commit_msg>Indentation tweaks<commit_after>function Serial(dataCallback, connectCallback) {

  var connected = false;                                  // whether or not a valid Quizmaster micro:bit is connected
  var CONNECTION_INFO = null;                             // holds the Chrome API serial connection info
  var serialBuffer = [];                                  // used to buffer data until we have a full commands
  chrome.serial.onReceive.addListener(onData);
  chrome.serial.onReceiveError.addListener(onError);

  /* Handles the buffering and parsing of any received data before passing it back to the main program */
  function onData(received)
  {
    var data = String.fromCharCode.apply(null, new Uint8Array(received.data));
    serialBuffer.push(data);
    // check if it's the end of the command
    if (data.lastIndexOf(";") > -1) {
      var response = serialBuffer.join("");
      var parsedResponse = response.split(/[;:]+/);
      parsedResponse.pop(); // remove the empty index
      if (!connected && parsedResponse[0] === "ack") {
        // only confirm a connection if the micro:bit acks the connect request ack
        // this means that only correctly flashed micro:bits can succesfully connect
        connected = true;
        connectCallback(connected);
      }
      dataCallback(parsedResponse);
      serialBuffer = [];
    }
  }

  /* Handles updating the connection state for common d/c errors */
  function onError(err) {
    if (!(err.error === "device_lost") && !(err.error === "disconnected") && !(err.error === "break"))
      throw new Error(err.error);
    connected = false;
    connectCallback(connected);
  }

  /* Convert given String to Uint8Array */
  function utf8ArrayBufFromStr(str)
  {
    var strUtf8 = unescape(encodeURIComponent(str));
    var arrayBuf = new Uint8Array(strUtf8.length);
    for (var i = 0; i < strUtf8.length; i++) {
      arrayBuf[i] = strUtf8.charCodeAt(i);
    }
    return arrayBuf;
  }

  /* Convert given Uint8Array to String */
  function strFromUtf8ArrayBuf(arrayBuf)
  {
    return escape(decodeURIComponent(String.fromCharCode.apply(null, arrayBuf)));
  }

  /* Attempts to write given string to the connected serial device */
  function write(str)
  {
    if (CONNECTION_INFO)
    {
      console.log(str);
      chrome.serial.send(CONNECTION_INFO.connectionId, utf8AbFromStr(str).buffer, function(info) { });
    }
  }

  /* Checks the connected serial devices for common micro:bit display names, if one matches, the callback provides the relevant port object (else it provides null) */
  function getMicrobitPort(callback) {
    chrome.serial.getDevices(function(portList) {
      for (var i = 0; i < portList.length; i++) {
        var port = portList[i];
        if ((port.displayName == 'mbed Serial Port') || ((port.displayName == 'MBED CMSIS_DAP') && (port.path.indexOf("tty") >= 0))) { // for windows and os x
          return callback(port);
        }
      }
      callback(null);
    });
  }

  /* Attempts to automatically find and connect to a microbit connected to the computer via serial
  /*    Callback provides a connected boolean (whether or not the connection was succesful) */
  function connect(callback) {
    getMicrobitPort(function(port) {
      if (port) {
        chrome.serial.connect(port.path, {bitrate: 115200}, function(connectionInfo) {
          if (chrome.runtime.lastError) {
            CONNECTION_INFO = null;
            connected = false;
            connectCallback(connected);
            console.log(chrome.runtime.lastError.message);
            return callback(connected);
          }
          else {
            // wait for micro:bit's ack response to ensure it's flashed correctly before confirming connection
            CONNECTION_INFO = connectionInfo;
            write("ack;");
            setTimeout(function() {
              if (!connected) {
                // connected micro:bit isn't flashed with the correct program
                callback(false);
              }
              else {
                callback(true);
              }
            }, 5000);
          }
        });
      }
      else {
        // no micro:bit found
        connected = false;
        connectCallback(connected);
        callback(false);
      }
    });
  }

  // initial connection attempt
  connect(()=>{});

  // public methods
  return {
    "write": function(str)
    {
      write(str);
    },
    "isConnected": function() {
      return connected;
    },
    "reconnect": function(callback) {
      if (connected)
        return callback(true);
      connect(callback);
    }
  }

}

export default Serial
<|endoftext|>


<commit_before>module("namespace");

test("retrieval and creation", function() {
	var ns = getNamespace("Test");

	ok(ns instanceof Namespace, "getNamespace returned a namespace");
	equals(ns, getNamespace("Test"), "multiple calls to getNamespace returns the same object");
	equals(ns.getName(), "Test", "the name of the current namespace is stored");
});

test("class creation", function() {
	var ns = getNamespace("Test1");

	ok(!ns.exists("A"), "checking for existience of undefined class");
	equals(ns.get("A"), null, "attempting to retieve a undefined class");

	// creating a single class
	var c = ns.create("A", {
		a : function() {
			return this;
		}
	});
	ok(!!c.__isclass_, "class created is a class object");
	ok(new c() instanceof base, "class creation created by extending the base class");
	equals(ns.A, c, "class reference is stored directly within namespace object");
	equals(ns.get("A"), c, "class reference is stored in internal reference array");
	equals(c.getNamespace(), ns, "namespaced class has a getter for the current namespace");

	// creating nested classes
	var d = ns.create("B.C", {
		b : function() {
			return this;
		}
	});
	equals(typeof ns.B, "object", "an intermediate container object is created by the namespace");
	ok(new d() instanceof base, "class creation created by extending the base class");
	equals(ns.B.C, d, "class reference is stored directly within namespace object (nested)");
	equals(ns.get("B.C"), d, "class reference is stored in internal reference array (nested)");
});

test("class extension and implementation using named references", function() {
	var ns = getNamespace("Test2");

	// extending a class with a named instance
	var c = ns.create("A", {
		a : function() {
			return 1;
		}
	});

	// extending a named reference in a namespace
	var d = ns.create("B", "A", {
		b : function() {
			return 2;
		}
	});
	equals(d.superclass, c, "extending classes using named references");
	equals(ns.B, d, "named reference is created within the namespace");

	// implementing classes using named references
	var e = ns.create("C", [ "A" ], {
		c : function() {
			return this;
		}
	});
	equals(e.prototype.a, c.prototype.a, "implementing a class using a named reference");
	equals(e.implement[0], c, "implement class reference stored internally");

	// implementing classes using a mixed reference
	var f = {
		d : function() {
			return 3;
		}
	};
	var g = ns.create("D", [ "A", f ], {
		e : function() {
			return 4;
		}
	});
	equals(g.prototype.a, c.prototype.a, "implementing a class using a named reference");
	equals(g.prototype.d, f.d, "implementing a object with a named reference");
	equals(g.implement[0], c, "implement class reference stored internally");
	equals(g.implement[1], f, "implement object reference stored internally");
});<commit_msg>unit tests for removing named classes from a namespace<commit_after>module("namespace");

test("retrieval and creation", function() {
	var ns = getNamespace("Test");

	ok(ns instanceof Namespace, "getNamespace returned a namespace");
	equals(ns, getNamespace("Test"), "multiple calls to getNamespace returns the same object");
	equals(ns.getName(), "Test", "the name of the current namespace is stored");
});

test("class creation", function() {
	var ns = getNamespace("Test1");

	ok(!ns.exists("A"), "checking for existience of undefined class");
	equals(ns.get("A"), null, "attempting to retieve a undefined class");

	// creating a single class
	var c = ns.create("A", {
		a : function() {
			return this;
		}
	});
	ok(!!c.__isclass_, "class created is a class object");
	ok(new c() instanceof base, "class creation created by extending the base class");
	equals(ns.A, c, "class reference is stored directly within namespace object");
	equals(ns.get("A"), c, "class reference is stored in internal reference array");
	equals(c.getNamespace(), ns, "namespaced class has a getter for the current namespace");

	// creating nested classes
	var d = ns.create("B.C", {
		b : function() {
			return this;
		}
	});
	equals(typeof ns.B, "object", "an intermediate container object is created by the namespace");
	ok(new d() instanceof base, "class creation created by extending the base class");
	equals(ns.B.C, d, "class reference is stored directly within namespace object (nested)");
	equals(ns.get("B.C"), d, "class reference is stored in internal reference array (nested)");
});

test("class extension and implementation using named references", function() {
	var ns = getNamespace("Test2");

	// extending a class with a named instance
	var c = ns.create("A", {
		a : function() {
			return 1;
		}
	});

	// extending a named reference in a namespace
	var d = ns.create("B", "A", {
		b : function() {
			return 2;
		}
	});
	equals(d.superclass, c, "extending classes using named references");
	equals(ns.B, d, "named reference is created within the namespace");

	// implementing classes using named references
	var e = ns.create("C", [ "A" ], {
		c : function() {
			return this;
		}
	});
	equals(e.prototype.a, c.prototype.a, "implementing a class using a named reference");
	equals(e.implement[0], c, "implement class reference stored internally");

	// implementing classes using a mixed reference
	var f = {
		d : function() {
			return 3;
		}
	};
	var g = ns.create("D", [ "A", f ], {
		e : function() {
			return 4;
		}
	});
	equals(g.prototype.a, c.prototype.a, "implementing a class using a named reference");
	equals(g.prototype.d, f.d, "implementing a object with a named reference");
	equals(g.implement[0], c, "implement class reference stored internally");
	equals(g.implement[1], f, "implement object reference stored internally");
});

test("removing named classes", function() {
	var ns = getNamespace("Test3");
	var ca = ns.create("A", {});
	var cb = ns.create("B", {});
	var cc = ns.create("A.C", {});
	var cd = ns.create("D", "A", {});
	var ce = ns.create("A.E", "A", {});
	var cf = ns.create("F", "A", {});

	// destroy an individual class
	ns.destroy("B");
	equals(typeof ns.B, "undefined", "removing a named class from the namespace");

	// destroy a class that is inherited from another class
	ns.destroy("D");
	equals(typeof ns.D, "undefined", "removing a named class from the namespace");
	equals(ns.A.subclass.indexOf(cd), -1, "remove class from the list of subclasses in the parent");

	// destroy a class namespace
	ns.destroy("A");
	equals(typeof ns.A, "undefined", "removing a named class from the namespace");
	equals(ns.get("A.C"), null, "removed leaf classes from branch namespace");
	equals(typeof ns.F, "undefined", "removed class that extended a destroyed class");
	equals(ns.get("F"), null, "removed branch namespace that inherited from a removed branch");
});
<|endoftext|>


<commit_before>import React from 'react';
import Background from './Background'

class Compass extends React.Component {
    static defaultProps = {
        color: "rgb(255, 128, 0)"
    };

    render() {
        let color = this.props.color;

        return (
            <svg width={100} height={100}>
                <Background />
                <g transform="translate(50,50)">
                    <circle r={48} stroke={color} strokeWidth={1} fill="none"/>
                    <g transform={this.props.direction}>
                        <g transform="translate(41, 0)">
                            <polygon points="6,0 0,4 0,-4" fill={color}/>
                        </g>
                    </g>
                </g>
            </svg>
        )
    }
}

export default Compass;
<commit_msg>Parameterize compass drawing to make it resizeable<commit_after>import React from 'react';
import Background from './Background'

class Compass extends React.Component {
    static defaultProps = {
        width: 100,
        height: 100,
        color: "rgb(255, 128, 0)"
    };

    render() {
        let padding     = 20,
            width       = this.props.width,
            height      = this.props.height,
            half_width  = width * 0.5,
            half_height = height * 0.5,
            origin      = `translate(${half_width}, ${half_height})`,
            radius      = (Math.min(width, height) - padding) * 0.5 - 1,
            color       = this.props.color,
            offset      = `translate(${radius - 6 - 1}, 0)`;

        return (
            <svg width={width} height={height}>
                <Background />
                <g transform={origin}>
                    <circle r={radius} stroke={color} strokeWidth={1} fill="none"/>
                    <g transform={this.props.direction}>
                        <g transform={offset}>
                            <polygon points="6,0 0,4 0,-4" fill={color}/>
                        </g>
                    </g>
                </g>
            </svg>
        )
    }
}

export default Compass;
<|endoftext|>


<commit_before>require('../support/test_helper.js');

var assert        = require('assert');
var Overviews     = require('../../lib/windshaft/utils/overviews');

function normalize_whitespace(txt) {
  return txt.replace(/\s+/g, " ").trim();
}

// compare SQL statements ignoring whitespace
function assertSameSql(sql1, sql2) {
    assert.equal(normalize_whitespace(sql1), normalize_whitespace(sql2));
}

describe('Overviews-support', function() {

  it('does not alter queries if no overviews data is present', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {};
    var overviews_sql = Overviews.query(sql, overviews);
    assert.equal(overviews_sql, sql);
    done();
  });

  it('does not alter queries which don\'t use overviews', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {
        table2: {
          0: { table: 'table2_ov0' },
          1: { table: 'table2_ov1' },
          4: { table: 'table2_ov4' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    assert.equal(overviews_sql, sql);
    done();
  });

  // jshint multistr:true

  it('generates query with single overview layer for level 0', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {
        table1: {
          0: { table: 'table1_ov0' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          vovw_table1 AS (\
            SELECT * FROM table1_ov0, vovw_scale WHERE vovw_z = 0\
            UNION ALL\
            SELECT * FROM table1, vovw_scale WHERE vovw_z > 0\
          )\
        SELECT * FROM vovw_table1\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

  it('generates query with single overview layer for level >0', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {
        table1: {
          2: { table: 'table1_ov2' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          vovw_table1 AS (\
            SELECT * FROM table1_ov2, vovw_scale WHERE vovw_z <= 2\
            UNION ALL\
            SELECT * FROM table1, vovw_scale WHERE vovw_z > 2\
          )\
        SELECT * FROM vovw_table1\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

  it('generates query with multiple overview layers for all levels up to N', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {
        table1: {
          0: { table: 'table1_ov0' },
          1: { table: 'table1_ov1' },
          2: { table: 'table1_ov2' },
          3: { table: 'table1_ov3' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          vovw_table1 AS (\
            SELECT * FROM table1_ov0, vovw_scale WHERE vovw_z = 0\
            UNION ALL\
            SELECT * FROM table1_ov1, vovw_scale WHERE vovw_z = 1\
            UNION ALL\
            SELECT * FROM table1_ov2, vovw_scale WHERE vovw_z = 2\
            UNION ALL\
            SELECT * FROM table1_ov3, vovw_scale WHERE vovw_z = 3\
            UNION ALL\
            SELECT * FROM table1, vovw_scale WHERE vovw_z > 3\
          )\
        SELECT * FROM vovw_table1\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

  it('generates query with multiple overview layers for random levels', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {
        table1: {
          0: { table: 'table1_ov0' },
          1: { table: 'table1_ov1' },
          6: { table: 'table1_ov6' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          vovw_table1 AS (\
            SELECT * FROM table1_ov0, vovw_scale WHERE vovw_z = 0\
            UNION ALL\
            SELECT * FROM table1_ov1, vovw_scale WHERE vovw_z = 1\
            UNION ALL\
            SELECT * FROM table1_ov6, vovw_scale WHERE vovw_z > 1 AND vovw_z <= 6\
            UNION ALL\
            SELECT * FROM table1, vovw_scale WHERE vovw_z > 6\
          )\
        SELECT * FROM vovw_table1\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

});
<commit_msg>Add tests for overviews queries with explicit schemas<commit_after>require('../support/test_helper.js');

var assert        = require('assert');
var Overviews     = require('../../lib/windshaft/utils/overviews');

function normalize_whitespace(txt) {
  return txt.replace(/\s+/g, " ").trim();
}

// compare SQL statements ignoring whitespace
function assertSameSql(sql1, sql2) {
    assert.equal(normalize_whitespace(sql1), normalize_whitespace(sql2));
}

describe('Overviews-support', function() {

  it('does not alter queries if no overviews data is present', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {};
    var overviews_sql = Overviews.query(sql, overviews);
    assert.equal(overviews_sql, sql);

    done();
  });

  it('does not alter queries which don\'t use overviews', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {
        table2: {
          0: { table: 'table2_ov0' },
          1: { table: 'table2_ov1' },
          4: { table: 'table2_ov4' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    assert.equal(overviews_sql, sql);
    done();
  });

  // jshint multistr:true

  it('generates query with single overview layer for level 0', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {
        table1: {
          0: { table: 'table1_ov0' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          vovw_table1 AS (\
            SELECT * FROM table1_ov0, vovw_scale WHERE vovw_z = 0\
            UNION ALL\
            SELECT * FROM table1, vovw_scale WHERE vovw_z > 0\
          )\
        SELECT * FROM vovw_table1\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

  it('generates query with single overview layer for level >0', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {
        table1: {
          2: { table: 'table1_ov2' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          vovw_table1 AS (\
            SELECT * FROM table1_ov2, vovw_scale WHERE vovw_z <= 2\
            UNION ALL\
            SELECT * FROM table1, vovw_scale WHERE vovw_z > 2\
          )\
        SELECT * FROM vovw_table1\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

  it('generates query with multiple overview layers for all levels up to N', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {
        table1: {
          0: { table: 'table1_ov0' },
          1: { table: 'table1_ov1' },
          2: { table: 'table1_ov2' },
          3: { table: 'table1_ov3' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          vovw_table1 AS (\
            SELECT * FROM table1_ov0, vovw_scale WHERE vovw_z = 0\
            UNION ALL\
            SELECT * FROM table1_ov1, vovw_scale WHERE vovw_z = 1\
            UNION ALL\
            SELECT * FROM table1_ov2, vovw_scale WHERE vovw_z = 2\
            UNION ALL\
            SELECT * FROM table1_ov3, vovw_scale WHERE vovw_z = 3\
            UNION ALL\
            SELECT * FROM table1, vovw_scale WHERE vovw_z > 3\
          )\
        SELECT * FROM vovw_table1\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

  it('generates query with multiple overview layers for random levels', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {
        table1: {
          0: { table: 'table1_ov0' },
          1: { table: 'table1_ov1' },
          6: { table: 'table1_ov6' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          vovw_table1 AS (\
            SELECT * FROM table1_ov0, vovw_scale WHERE vovw_z = 0\
            UNION ALL\
            SELECT * FROM table1_ov1, vovw_scale WHERE vovw_z = 1\
            UNION ALL\
            SELECT * FROM table1_ov6, vovw_scale WHERE vovw_z > 1 AND vovw_z <= 6\
            UNION ALL\
            SELECT * FROM table1, vovw_scale WHERE vovw_z > 6\
          )\
        SELECT * FROM vovw_table1\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

  it('generates query for a table with explicit schema', function(done){
    var sql = "SELECT * FROM public.table1";
    var overviews = {
        'public.table1': {
          2: { table: 'table1_ov2' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          vovw_table1 AS (\
            SELECT * FROM public.table1_ov2, vovw_scale WHERE vovw_z <= 2\
            UNION ALL\
            SELECT * FROM public.table1, vovw_scale WHERE vovw_z > 2\
          )\
        SELECT * FROM vovw_table1\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

  it('generates query for a table with explicit schema in the overviews info', function(done){
    var sql = "SELECT * FROM table1";
    var overviews = {
        'public.table1': {
          2: { table: 'table1_ov2' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          vovw_table1 AS (\
            SELECT * FROM public.table1_ov2, vovw_scale WHERE vovw_z <= 2\
            UNION ALL\
            SELECT * FROM public.table1, vovw_scale WHERE vovw_z > 2\
          )\
        SELECT * FROM vovw_table1\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

  it('generates query for a table that needs quoting with explicit schema', function(done){
    var sql = "SELECT * FROM public.\"table 1\"";
    var overviews = {
        'public."table 1"': {
          2: { table: '"table 1_ov2"' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          \"vovw_table 1\" AS (\
            SELECT * FROM public.\"table 1_ov2\", vovw_scale WHERE vovw_z <= 2\
            UNION ALL\
            SELECT * FROM public.\"table 1\", vovw_scale WHERE vovw_z > 2\
          )\
        SELECT * FROM \"vovw_table 1\"\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

  it('generates query for a table with explicit schema that needs quoting', function(done){
    var sql = "SELECT * FROM \"user-1\".table1";
    var overviews = {
        '"user-1".table1': {
          2: { table: 'table1_ov2' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          vovw_table1 AS (\
            SELECT * FROM \"user-1\".table1_ov2, vovw_scale WHERE vovw_z <= 2\
            UNION ALL\
            SELECT * FROM \"user-1\".table1, vovw_scale WHERE vovw_z > 2\
          )\
        SELECT * FROM vovw_table1\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

  it('generates query for a table with explicit schema both needing quoting', function(done){
    var sql = "SELECT * FROM \"user-1\".\"table 1\"";
    var overviews = {
        '"user-1"."table 1"': {
          2: { table: '"table 1_ov2"' }
        }
    };
    var overviews_sql = Overviews.query(sql, overviews);
    var expected_sql = "\
        WITH\
          vovw_scale AS ( SELECT CDB_ZoomFromScale(!scale_denominator!) AS vovw_z ),\
          \"vovw_table 1\" AS (\
            SELECT * FROM \"user-1\".\"table 1_ov2\", vovw_scale WHERE vovw_z <= 2\
            UNION ALL\
            SELECT * FROM \"user-1\".\"table 1\", vovw_scale WHERE vovw_z > 2\
          )\
        SELECT * FROM \"vovw_table 1\"\
    ";
    assertSameSql(overviews_sql, expected_sql);
    done();
  });

});
<|endoftext|>


<commit_before>const spreadPromiseArgs = (promise, func) => (
	promise
	.then(args => Promise.all(args))
	.then(args => func.apply(promise, args))
)

const spreadablePromise = promise => ({
	catch: promise.catch.bind(promise),
	then: func => (
		promise.then(spreadPromiseArgs(promise, func))
	),
})

const handleCallback = (resolve, reject) => (
	(err, ...callbackArgs) => (
		err
		? reject(err)
		: resolve(callbackArgs)
	)
)

const promisify = functionWithCallback => (...functionArgs) => (
	spreadablePromise(
		new Promise(
			(resolve, reject) => (
				functionWithCallback(
					...functionArgs,
					handleCallback(resolve, reject)
				)
			)
		)
	)
)

module.exports = promisify
<commit_msg>Updated promisify utility with `.catch()` error logging<commit_after>const dir = require(`${global.baseDir}/global-dirs`)
const logger = require(`${dir.utils}/logger`)

const spreadPromiseArgs = (promise, func) => (
	promise
	.then(args => Promise.all(args))
	.then(args => func.apply(promise, args))
	.catch(logger.logError)
)

const spreadablePromise = promise => ({
	catch: promise.catch.bind(promise),
	then: func => (
		promise
		.then(spreadPromiseArgs(promise, func))
		.catch(logger.logError)
	),
})

const handleCallback = (resolve, reject) => (
	(err, ...callbackArgs) => (
		err
		? reject(err)
		: resolve(callbackArgs)
	)
)

const promisify = functionWithCallback => (...functionArgs) => (
	spreadablePromise(
		new Promise(
			(resolve, reject) => (
				functionWithCallback(
					...functionArgs,
					handleCallback(resolve, reject)
				)
			)
		)
	)
)

module.exports = promisify
<|endoftext|>


<commit_before>'use strict';
var assert = require('chai').assert;
var request = require('supertest');
var app = require('../app');

describe('Array', function() {
    describe('#indexOf()', function () {
        it('should return -1 when the value is not present', function () {
            assert.equal(-1, [1,2,3].indexOf(5));
            assert.equal(-1, [1,2,3].indexOf(0));
        });
    });
});
<commit_msg>fixed test<commit_after>'use strict';
var assert = require('chai').assert;
var request = require('supertest');
var app = require('../../app');

describe('Array', function() {
    describe('#indexOf()', function () {
        it('should return -1 when the value is not present', function () {
            assert.equal(-1, [1,2,3].indexOf(5));
            assert.equal(-1, [1,2,3].indexOf(0));
        });
    });
});
<|endoftext|>


<commit_before>"use strict";
var Utils = {
  makeNullProto: function() {
    return {__proto__: null};
  },
  fetchHttpContents: function(url, success) {
    var req = new XMLHttpRequest();
    req.open("GET", url, true);
    req.onreadystatechange = function () {
      if (this.readyState === 4 && this.status === 200) {
        success(this.responseText);
      }
    };
    req.send();
    return req;
  },
  _escapeRe: /[&<>]/g,
  _escapeCallback: function(c, n) {
    n = c.charCodeAt(0);
    return (n === 60) ? "<" : (n === 62) ? ">" : "&";
  },
  escapeHtml: function(s) {
    return s.replace(this._escapeRe, this._escapeCallback);
  },
  // "javascript" should be treated specially
  _nonUrlPrefixes: { about: 1, blob: 1, data: 1, "view-source": 1 },
  _chromePrefixes: { "chrome-extension": 1, "chrome-search": 1 },
  _urlPrefix: /^[a-z]{3,}:\/\//,
  hasOrdinaryUrlPrefix: function(url) {
    return this._urlPrefix.test(url);
  },
  // url: only accept real tab's
  isRefusingIncognito: function(url) {
    url = url.toLowerCase();
    if (url.startsWith('chrome://')) {
      return !url.startsWith("chrome://downloads");
    }
    return !url.startsWith(Settings.CONST.ChromeInnerNewTab) && url.startsWith('chrome');
  },
  _hostRe: /^([^:]+(:[^:]+)?@)?([^:]+|\[[^\]]+\])(:\d+)?$/,
  _nonENTlds: ".\u4e2d\u56fd",
  _tlds: ["", "",
    ".ac.ad.ae.af.ag.ai.al.am.an.ao.aq.ar.as.at.au.aw.az.ba.bb.bd.be.bf.bg.bh.bi.bj.bm.bn.bo.br.bs.bt.bv.bw.by.bz.ca.cc.cd.cf.cg.ch.ci.ck.cl.cm.cn.co.cr.cu.cv.cx.cy.cz.de.dj.dk.dm.do.dz.ec.ee.eg.eh.er.es.et.eu.fi.fj.fk.fm.fo.fr.ga.gd.ge.gf.gg.gh.gi.gl.gm.gn.gp.gq.gr.gs.gt.gu.gw.gy.hk.hm.hn.hr.ht.hu.id.ie.il.im.in.io.iq.ir.is.it.je.jm.jo.jp.ke.kg.kh.ki.km.kn.kp.kr.kw.ky.kz.la.lb.lc.li.lk.lr.ls.lt.lu.lv.ly.ma.mc.md.me.mg.mh.mk.ml.mm.mn.mo.mp.mq.mr.ms.mt.mu.mv.mw.mx.my.mz.na.nc.ne.nf.ng.ni.nl.no.np.nr.nu.nz.om.pa.pe.pf.pg.ph.pk.pl.pm.pn.pr.ps.pt.pw.py.qa.re.ro.ru.rw.sa.sb.sc.sd.se.sg.sh.si.sj.sk.sl.sm.sn.so.sr.ss.st.su.sv.sy.sz.tc.td.tf.tg.th.tj.tk.tl.tm.tn.to.tp.tr.tt.tv.tw.tz.ua.ug.uk.um.us.uy.uz.va.vc.ve.vg.vi.vn.vu.wf.ws.ye.yt.yu.za.zm.zw",
    ".biz.cat.com.edu.gov.int.mil.mtn.net.org.pro.tel.top.xxx",
    ".aero.arpa.asia.club.coop.info.jobs.mobi.name.post",
    ".local",
    ".museum.travel"
  ],
  _ipRe: /^(\d{1,3}\.){3}\d{1,3}$/,
  spacesRe: /[\s\u3000]+/g,
  _nonENTldRe: /[^a-z]/,
  _jsNotEscapeRe: /["\[\]{}\u00ff-\uffff]|%(?![\dA-F]{2}|[\da-f]{2})/,
  filePathRe: /^['"]?((?:[A-Za-z]:[\\/]|\/(?:Users|home|root)\/)[^'"]*)['"]?$/,
  convertToUrl: function(string, keyword) {
    if (string.substring(0, 11).toLowerCase() === "javascript:") {
      if (Settings.CONST.ChromeVersion < 46 && string.indexOf('%', 11) > 0
          && !this._jsNotEscapeRe.test(string)) {
        string = this.decodeURLPart(string);
      }
      return string;
    }
    var type = -1, expected = 1, index, index2, oldString, arr;
    // NOTE: here '\u3000' is changed to ' ', which may cause a 404 (for url)
    // NOTE: here a mulit-line string is be changed to single-line,
    //       which may be better
    oldString = string.replace(this.spacesRe, ' ').trim();
    string = oldString.toLowerCase();
    if ((index = string.indexOf(' ')) > 0) {
      string = string.substring(0, index);
    }
    if ((index = string.indexOf(':')) === 0) { type = 2; }
    else if (index === -1 || string.substring(index, index + 3) !== "://") {
      if (index !== -1 && string.substring(0, index) in this._nonUrlPrefixes) {
        index2 = string.length;
        type = index2 < oldString.length || index2 <= index
          || string.charCodeAt(index + 1) === 47 ? 2 : 0;
      } else if ((index = string.indexOf('/')) <= 0) {
        if (index === 0 || string.length < oldString.length) { type = 2; }
      } else if (string.length >= oldString.length ||
          ((index2 = string.charCodeAt(index + 1)) > 32 && index2 !== 47)) {
        string = string.substring(0, index);
      } else {
        type = 2;
      }
    }
    else if (this._nonENTldRe.test(string.substring(0, index))) {
      type = (string.substring(0, index) in this._chromePrefixes)
        && (index = string.charCodeAt(index + 3)) > 32 && index !== 47 ? 0 : 2;
    }
    else if (string.startsWith("file:")) {
      if (string.charCodeAt(7) !== 47) {
        type = 2;
      } else {
        index = string.charCodeAt(8);
        type = (index > 32 && index !== 47) ? 0 : 2; // `>32`: in case of NaN
      }
    }
    else if (string.startsWith("chrome:")) {
      type = string.length < oldString.length && string.indexOf('/', 9) === -1
        ? 2 : 0;
    }
    else if (string.startsWith("vimium:")) {
      type = 0;
      oldString = chrome.runtime.getURL("/") + oldString.substring(9);
    }
    else if (index2 = string.indexOf('/', index += 3),
        string.length >= oldString.length) {
      string = string.substring(index, index2 !== -1 ? index2 : undefined);
      expected = 0;
    }
    else if (index2 <= index || (expected = string.charCodeAt(index2 + 1),
        !(expected > 32) || expected === 47 )) {
      type = 2;
    } else {
      string = string.substring(index, index2);
      expected = 0;
    }

    if (type !== -1) {
    } else if (!(arr = this._hostRe.exec(string))) {
      type = 2;
    } else if ((string = arr[3]).indexOf(':') !== -1
        || string.endsWith("localhost")) {
      type = expected;
    } else if ((index = string.lastIndexOf('.')) <= 0) {
      type = 2;
    } else if (this._ipRe.test(string)) {
      type = expected;
    } else if (!this.isTld(string.substring(index + 1))) {
      type = 2;
    } else if (expected === 0) {
      type = 0;
    } else if (arr[2] || arr[4] || !arr[1] || string.startsWith("ftp")) {
      type = 1;
    // the below means string is like "(?<=abc@)(uvw.)*xyz.tld"
    } else if (string.startsWith("mail") || string.indexOf(".mail") > 0
        || (index2 = string.indexOf(".")) === index) {
      type = 2;
    } else if (string.indexOf(".", ++index2) !== index) {
      type = 1;
    } else {
      type = this.isTld(string.substring(index2, index)) ? 2 : 1;
    }
    // window.type = type;
    return type === 0 ? oldString : type === 1 ? ("http://" + oldString)
      : this.createSearchUrl(Settings.get("searchEnginesMap")[
          keyword || "~"], oldString.split(' ')).url;
  },
  isTld: function(tld) {
    if (this._nonENTldRe.test(tld)) {
      return this._nonENTlds.indexOf(tld) !== -1;
    } else if (tld.length < this._tlds.length) {
      return this._tlds[tld.length].indexOf(tld) > 0;
    }
    return false;
  },
  searchWordRe: /%[sS]/g,
  createSearchUrl: function(pattern, query, $S) {
    if ($S != null ? ($S === true) : pattern.$S) {
      $S = query.join(' ');
    }
    if (pattern.$s) {
      query = query.map(encodeURIComponent).join('+');
    }
    return {
      url: pattern.url.replace(this.searchWordRe, function(s) {
        return (s === "%s") ? query : $S;
      }),
      $s: query,
      $S: $S
    };
  },
  decodeURLPart: function(url) {
    try {
      url = decodeURIComponent(url);
    } catch (e) {}
    return url;
  },
  parseSearchEngines: function(searchEnginesText, map) {
    var a, pairs, key, val, name, obj, _i, _j, _len, _len2, key0, //
    rEscapeSpace = /\\\s/g, rSpace = /\s/, rEscapeS = /\\s/g, rColon = /\\:/g;
    a = searchEnginesText.replace(/\\\n/g, '').split('\n');
    for (_i = 0, _len = a.length; _i < _len; _i++) {
      val = a[_i].trim();
      if (!(val.charCodeAt(0) > 35)) { continue; } // mask: /[ !"#]/
      _j = 0;
      do {
        _j = val.indexOf(":", _j + 1);
      } while (val[_j - 1] === '\\');
      if (_j <= 0 || !(key = val.substring(0, _j).trimRight())) continue;
      val = val.substring(_j + 1).trimLeft();
      if (!val) continue;
      val = val.replace(rEscapeSpace, "\\s");
      _j = val.search(rSpace);
      if (_j > 0) {
        name = val.substring(_j + 1).trimLeft();
        key0 = "";
        val = val.substring(0, _j);
      } else {
        name = null;
      }
      val = val.replace(rEscapeS, " ");
      obj = {url: val};
      key = key.replace(rColon, ":");
      pairs = key.split('|');
      for (_j = 0, _len2 = pairs.length; _j < _len2; _j++) {
        if (key = pairs[_j].trim()) {
          if (name) {
            if (!key0) { key0 = key; }
          } else {
            key0 = name = key;
          }
          map[key] = obj;
        }
      }
      if (!name) continue;
      obj.name = name;
      obj.$s = val.indexOf("%s") + 1;
      obj.$S = val.indexOf("%S") + 1;
      if (pairs = this.reparseSearchUrl(obj, key0)) {
        map[""].push(pairs);
      }
    }
  },
  reparseSearchUrl: function (pattern, name) {
    var url, ind = pattern.$s || pattern.$S, prefix;
    if (!ind) { return; }
    url = pattern.url.toLowerCase();
    if (!(this.hasOrdinaryUrlPrefix(url) || url.startsWith("chrome-"))) { return; }
    url = url.substring(0, ind - 1);
    if (ind = (url.indexOf("?") + 1) || (url.indexOf("#") + 1)) {
      prefix = url.substring(0, ind - 1);
      url = url.substring(ind);
      if (ind = url.lastIndexOf("&") + 1) {
        url = url.substring(ind);
      }
      if (url && url !== "=" && !url.endsWith("/")) {
        return this.makeReparser(prefix, "[?#&]", url, "([^&#]*)", name)
      }
      url = pattern.url.substring(0, (pattern.$s || pattern.$S) - 1);
    }
    prefix = url;
    url = pattern.url.substring(url.length + 2);
    if (ind = (url.indexOf("?") + 1) || (url.indexOf("#") + 1)) {
      url = url.substring(0, ind);
    }
    return this.makeReparser(prefix, "^([^?#]*)", url, "", name);
  },
  escapeAllRe: /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  makeReparser: function(head, prefix, url, suffix, name) {
    url = url.toLowerCase().replace(this.escapeAllRe, "\\$&");
    if (head.startsWith("https://")) {
      head = "http" + head.substring(5);
    } else if (head.toLowerCase().startsWith("vimium://")) {
      head = chrome.runtime.getURL("/") + head.substring(9);
    }
    return [head, new RegExp(prefix + url + suffix, "i"), name];
  },
  Decoder: null,
  upperRe: /[A-Z]/
};

if (!String.prototype.startsWith) {
String.prototype.startsWith = function(s) {
  return this.length >= s.length && this.lastIndexOf(s, 0) === 0;
};
String.prototype.endsWith || (String.prototype.endsWith = function(s) {
  var i = this.length - s.length;
  return i >= 0 && this.indexOf(s, i) === i;
});
}
<commit_msg>noop; rework createSearchUrl<commit_after>"use strict";
var Utils = {
  makeNullProto: function() {
    return {__proto__: null};
  },
  fetchHttpContents: function(url, success) {
    var req = new XMLHttpRequest();
    req.open("GET", url, true);
    req.onreadystatechange = function () {
      if (this.readyState === 4 && this.status === 200) {
        success(this.responseText);
      }
    };
    req.send();
    return req;
  },
  _escapeRe: /[&<>]/g,
  _escapeCallback: function(c, n) {
    n = c.charCodeAt(0);
    return (n === 60) ? "<" : (n === 62) ? ">" : "&";
  },
  escapeHtml: function(s) {
    return s.replace(this._escapeRe, this._escapeCallback);
  },
  // "javascript" should be treated specially
  _nonUrlPrefixes: { about: 1, blob: 1, data: 1, "view-source": 1 },
  _chromePrefixes: { "chrome-extension": 1, "chrome-search": 1 },
  _urlPrefix: /^[a-z]{3,}:\/\//,
  hasOrdinaryUrlPrefix: function(url) {
    return this._urlPrefix.test(url);
  },
  // url: only accept real tab's
  isRefusingIncognito: function(url) {
    url = url.toLowerCase();
    if (url.startsWith('chrome://')) {
      return !url.startsWith("chrome://downloads");
    }
    return !url.startsWith(Settings.CONST.ChromeInnerNewTab) && url.startsWith('chrome');
  },
  _hostRe: /^([^:]+(:[^:]+)?@)?([^:]+|\[[^\]]+\])(:\d+)?$/,
  _nonENTlds: ".\u4e2d\u56fd",
  _tlds: ["", "",
    ".ac.ad.ae.af.ag.ai.al.am.an.ao.aq.ar.as.at.au.aw.az.ba.bb.bd.be.bf.bg.bh.bi.bj.bm.bn.bo.br.bs.bt.bv.bw.by.bz.ca.cc.cd.cf.cg.ch.ci.ck.cl.cm.cn.co.cr.cu.cv.cx.cy.cz.de.dj.dk.dm.do.dz.ec.ee.eg.eh.er.es.et.eu.fi.fj.fk.fm.fo.fr.ga.gd.ge.gf.gg.gh.gi.gl.gm.gn.gp.gq.gr.gs.gt.gu.gw.gy.hk.hm.hn.hr.ht.hu.id.ie.il.im.in.io.iq.ir.is.it.je.jm.jo.jp.ke.kg.kh.ki.km.kn.kp.kr.kw.ky.kz.la.lb.lc.li.lk.lr.ls.lt.lu.lv.ly.ma.mc.md.me.mg.mh.mk.ml.mm.mn.mo.mp.mq.mr.ms.mt.mu.mv.mw.mx.my.mz.na.nc.ne.nf.ng.ni.nl.no.np.nr.nu.nz.om.pa.pe.pf.pg.ph.pk.pl.pm.pn.pr.ps.pt.pw.py.qa.re.ro.ru.rw.sa.sb.sc.sd.se.sg.sh.si.sj.sk.sl.sm.sn.so.sr.ss.st.su.sv.sy.sz.tc.td.tf.tg.th.tj.tk.tl.tm.tn.to.tp.tr.tt.tv.tw.tz.ua.ug.uk.um.us.uy.uz.va.vc.ve.vg.vi.vn.vu.wf.ws.ye.yt.yu.za.zm.zw",
    ".biz.cat.com.edu.gov.int.mil.mtn.net.org.pro.tel.top.xxx",
    ".aero.arpa.asia.club.coop.info.jobs.mobi.name.post",
    ".local",
    ".museum.travel"
  ],
  _ipRe: /^(\d{1,3}\.){3}\d{1,3}$/,
  spacesRe: /[\s\u3000]+/g,
  _nonENTldRe: /[^a-z]/,
  _jsNotEscapeRe: /["\[\]{}\u00ff-\uffff]|%(?![\dA-F]{2}|[\da-f]{2})/,
  filePathRe: /^['"]?((?:[A-Za-z]:[\\/]|\/(?:Users|home|root)\/)[^'"]*)['"]?$/,
  convertToUrl: function(string, keyword) {
    if (string.substring(0, 11).toLowerCase() === "javascript:") {
      if (Settings.CONST.ChromeVersion < 46 && string.indexOf('%', 11) > 0
          && !this._jsNotEscapeRe.test(string)) {
        string = this.decodeURLPart(string);
      }
      return string;
    }
    var type = -1, expected = 1, index, index2, oldString, arr;
    // NOTE: here '\u3000' is changed to ' ', which may cause a 404 (for url)
    // NOTE: here a mulit-line string is be changed to single-line,
    //       which may be better
    oldString = string.replace(this.spacesRe, ' ').trim();
    string = oldString.toLowerCase();
    if ((index = string.indexOf(' ')) > 0) {
      string = string.substring(0, index);
    }
    if ((index = string.indexOf(':')) === 0) { type = 2; }
    else if (index === -1 || string.substring(index, index + 3) !== "://") {
      if (index !== -1 && string.substring(0, index) in this._nonUrlPrefixes) {
        index2 = string.length;
        type = index2 < oldString.length || index2 <= index
          || string.charCodeAt(index + 1) === 47 ? 2 : 0;
      } else if ((index = string.indexOf('/')) <= 0) {
        if (index === 0 || string.length < oldString.length) { type = 2; }
      } else if (string.length >= oldString.length ||
          ((index2 = string.charCodeAt(index + 1)) > 32 && index2 !== 47)) {
        string = string.substring(0, index);
      } else {
        type = 2;
      }
    }
    else if (this._nonENTldRe.test(string.substring(0, index))) {
      type = (string.substring(0, index) in this._chromePrefixes)
        && (index = string.charCodeAt(index + 3)) > 32 && index !== 47 ? 0 : 2;
    }
    else if (string.startsWith("file:")) {
      if (string.charCodeAt(7) !== 47) {
        type = 2;
      } else {
        index = string.charCodeAt(8);
        type = (index > 32 && index !== 47) ? 0 : 2; // `>32`: in case of NaN
      }
    }
    else if (string.startsWith("chrome:")) {
      type = string.length < oldString.length && string.indexOf('/', 9) === -1
        ? 2 : 0;
    }
    else if (string.startsWith("vimium:")) {
      type = 0;
      oldString = chrome.runtime.getURL("/") + oldString.substring(9);
    }
    else if (index2 = string.indexOf('/', index += 3),
        string.length >= oldString.length) {
      string = string.substring(index, index2 !== -1 ? index2 : undefined);
      expected = 0;
    }
    else if (index2 <= index || (expected = string.charCodeAt(index2 + 1),
        !(expected > 32) || expected === 47 )) {
      type = 2;
    } else {
      string = string.substring(index, index2);
      expected = 0;
    }

    if (type !== -1) {
    } else if (!(arr = this._hostRe.exec(string))) {
      type = 2;
    } else if ((string = arr[3]).indexOf(':') !== -1
        || string.endsWith("localhost")) {
      type = expected;
    } else if ((index = string.lastIndexOf('.')) <= 0) {
      type = 2;
    } else if (this._ipRe.test(string)) {
      type = expected;
    } else if (!this.isTld(string.substring(index + 1))) {
      type = 2;
    } else if (expected === 0) {
      type = 0;
    } else if (arr[2] || arr[4] || !arr[1] || string.startsWith("ftp")) {
      type = 1;
    // the below means string is like "(?<=abc@)(uvw.)*xyz.tld"
    } else if (string.startsWith("mail") || string.indexOf(".mail") > 0
        || (index2 = string.indexOf(".")) === index) {
      type = 2;
    } else if (string.indexOf(".", ++index2) !== index) {
      type = 1;
    } else {
      type = this.isTld(string.substring(index2, index)) ? 2 : 1;
    }
    // window.type = type;
    return type === 0 ? oldString : type === 1 ? ("http://" + oldString)
      : this.createSearchUrl(Settings.get("searchEnginesMap")[
          keyword || "~"], oldString.split(' ')).url;
  },
  isTld: function(tld) {
    if (this._nonENTldRe.test(tld)) {
      return this._nonENTlds.indexOf(tld) !== -1;
    } else if (tld.length < this._tlds.length) {
      return this._tlds[tld.length].indexOf(tld) > 0;
    }
    return false;
  },
  searchWordRe: /%[sS]/g,
  createSearchUrl: function(pattern, query, $S) {
    var queryStr;
    if ($S != null ? ($S === true) : pattern.$S) {
      $S = query.join(' ');
    }
    if (pattern.$s) {
      queryStr = query.map(encodeURIComponent).join('+');
    }
    return {
      url: pattern.url.replace(this.searchWordRe, function(s) {
        return (s === "%s") ? queryStr : $S;
      }),
      $s: queryStr,
      $S: $S
    };
  },
  decodeURLPart: function(url) {
    try {
      url = decodeURIComponent(url);
    } catch (e) {}
    return url;
  },
  parseSearchEngines: function(searchEnginesText, map) {
    var a, pairs, key, val, name, obj, _i, _j, _len, _len2, key0, //
    rEscapeSpace = /\\\s/g, rSpace = /\s/, rEscapeS = /\\s/g, rColon = /\\:/g;
    a = searchEnginesText.replace(/\\\n/g, '').split('\n');
    for (_i = 0, _len = a.length; _i < _len; _i++) {
      val = a[_i].trim();
      if (!(val.charCodeAt(0) > 35)) { continue; } // mask: /[ !"#]/
      _j = 0;
      do {
        _j = val.indexOf(":", _j + 1);
      } while (val[_j - 1] === '\\');
      if (_j <= 0 || !(key = val.substring(0, _j).trimRight())) continue;
      val = val.substring(_j + 1).trimLeft();
      if (!val) continue;
      val = val.replace(rEscapeSpace, "\\s");
      _j = val.search(rSpace);
      if (_j > 0) {
        name = val.substring(_j + 1).trimLeft();
        key0 = "";
        val = val.substring(0, _j);
      } else {
        name = null;
      }
      val = val.replace(rEscapeS, " ");
      obj = {url: val};
      key = key.replace(rColon, ":");
      pairs = key.split('|');
      for (_j = 0, _len2 = pairs.length; _j < _len2; _j++) {
        if (key = pairs[_j].trim()) {
          if (name) {
            if (!key0) { key0 = key; }
          } else {
            key0 = name = key;
          }
          map[key] = obj;
        }
      }
      if (!name) continue;
      obj.name = name;
      obj.$s = val.indexOf("%s") + 1;
      obj.$S = val.indexOf("%S") + 1;
      if (pairs = this.reparseSearchUrl(obj, key0)) {
        map[""].push(pairs);
      }
    }
  },
  reparseSearchUrl: function (pattern, name) {
    var url, ind = pattern.$s || pattern.$S, prefix;
    if (!ind) { return; }
    url = pattern.url.toLowerCase();
    if (!(this.hasOrdinaryUrlPrefix(url) || url.startsWith("chrome-"))) { return; }
    url = url.substring(0, ind - 1);
    if (ind = (url.indexOf("?") + 1) || (url.indexOf("#") + 1)) {
      prefix = url.substring(0, ind - 1);
      url = url.substring(ind);
      if (ind = url.lastIndexOf("&") + 1) {
        url = url.substring(ind);
      }
      if (url && url !== "=" && !url.endsWith("/")) {
        return this.makeReparser(prefix, "[?#&]", url, "([^&#]*)", name)
      }
      url = pattern.url.substring(0, (pattern.$s || pattern.$S) - 1);
    }
    prefix = url;
    url = pattern.url.substring(url.length + 2);
    if (ind = (url.indexOf("?") + 1) || (url.indexOf("#") + 1)) {
      url = url.substring(0, ind);
    }
    return this.makeReparser(prefix, "^([^?#]*)", url, "", name);
  },
  escapeAllRe: /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  makeReparser: function(head, prefix, url, suffix, name) {
    url = url.toLowerCase().replace(this.escapeAllRe, "\\$&");
    if (head.startsWith("https://")) {
      head = "http" + head.substring(5);
    } else if (head.toLowerCase().startsWith("vimium://")) {
      head = chrome.runtime.getURL("/") + head.substring(9);
    }
    return [head, new RegExp(prefix + url + suffix, "i"), name];
  },
  Decoder: null,
  upperRe: /[A-Z]/
};

if (!String.prototype.startsWith) {
String.prototype.startsWith = function(s) {
  return this.length >= s.length && this.lastIndexOf(s, 0) === 0;
};
String.prototype.endsWith || (String.prototype.endsWith = function(s) {
  var i = this.length - s.length;
  return i >= 0 && this.indexOf(s, i) === i;
});
}
<|endoftext|>