<commit_before>import React from 'react';
import Enzyme, { mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import ClampLines from 'clamp-lines';

Enzyme.configure({ adapter: new Adapter() });

describe('ClampLines', () => {
  const content =
    'Zent ( ˈzent ) 是有赞 PC 端 WebUI 规范的 React 实现，提供了一整套基础的 UI 组件以及一些常用的业务组件。目前我们有 50+ 组件，这些组件都已经在有赞的各类 PC 业务中使用，我们会在此基础上，持续开发一些新组件。我们的目标是让 React 项目开发更快、更简单。';
  it('basic', () => {
    const wrapper = mount(
      <ClampLines lines={2} popWidth={400} text={content} />
    );
    const props = wrapper.props();
    const instance = wrapper.find(ClampLines).instance();
    instance.maxHeight = 40;
    instance.lineHeight = 20;
    instance.element = {
      clientHeight: 20,
    };
    instance.innerElement = {
      textContent: '',
    };
    instance.clampLines();
    instance.state.noClamp = false;
    instance.render();
    expect(props.prefix).toBe('zent');
    expect(wrapper.state().noClamp).toBe(false);
    expect(instance.innerElement.textContent).toBe(content);
  });

  it('do not show pop', () => {
    const wrapper = mount(
      <ClampLines lines={2} popWidth={400} text={content} showPop={false} />
    );
    const instance = wrapper.find(ClampLines).instance();
    instance.innerElement = {
      textContent: '',
    };
    instance.state.noClamp = false;
    const spy = jest.spyOn(instance, 'renderClampedText');
    instance.render();
    expect(spy).toBeCalled();
  });

  it('empty text', () => {
    const wrapper = mount(<ClampLines lines={2} popWidth={400} text="" />);
    const instance = wrapper.find(ClampLines).instance();
    expect(instance.innerElement).toBe(null);
  });

  it('resizable', () => {
    const wrapper = mount(
      <ClampLines lines={2} popWidth={400} resizable text="" />
    );
    const instance = wrapper.find(ClampLines).instance();
    instance.element = {
      clientHeight: 20,
    };
    instance.innerElement = {
      textContent: '',
    };
    const spy = jest.spyOn(instance, 'clampLines');
    instance.handleResize();
    jest.runAllTimers();
    expect(spy).toBeCalled();
  });
});
<commit_msg>Fix tests<commit_after>import React from 'react';
import Enzyme, { mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import ClampLines from 'clamp-lines';

Enzyme.configure({ adapter: new Adapter() });

describe('ClampLines', () => {
  const content =
    'Zent ( ˈzent ) 是有赞 PC 端 WebUI 规范的 React 实现，提供了一整套基础的 UI 组件以及一些常用的业务组件。目前我们有 50+ 组件，这些组件都已经在有赞的各类 PC 业务中使用，我们会在此基础上，持续开发一些新组件。我们的目标是让 React 项目开发更快、更简单。';
  it('basic', () => {
    const wrapper = mount(
      <ClampLines lines={2} popWidth={400} text={content} />
    );
    const props = wrapper.props();
    const instance = wrapper.find(ClampLines).instance();
    instance.maxHeight = 40;
    instance.lineHeight = 20;
    instance.element = {
      clientHeight: 20,
    };
    instance.innerElement = {
      textContent: '',
    };
    instance.clampLines();
    instance.state.noClamp = false;
    instance.render();
    expect(props.prefix).toBe('zent');
    expect(wrapper.state().noClamp).toBe(false);
    expect(instance.innerElement.textContent).toBe(content);
  });

  it('do not show pop', () => {
    const wrapper = mount(
      <ClampLines lines={2} popWidth={400} text={content} showPop={false} />
    );
    const instance = wrapper.find(ClampLines).instance();
    instance.innerElement = {
      textContent: '',
    };
    instance.state.noClamp = false;
    const spy = jest.spyOn(instance, 'renderClampedText');
    instance.render();
    expect(spy).toBeCalled();
  });

  it('empty text', () => {
    const wrapper = mount(<ClampLines lines={2} popWidth={400} text="" />);
    const instance = wrapper.find(ClampLines).instance();
    expect(instance.innerElement).toBe(null);
  });

  it('resizable', () => {
    const wrapper = mount(
      <ClampLines delay={0} lines={2} popWidth={400} resizable text="" />
    );
    const instance = wrapper.find(ClampLines).instance();
    instance.element = {
      clientHeight: 20,
    };
    instance.innerElement = {
      textContent: '',
    };
    const spy = jest.spyOn(instance, 'clampLines');
    instance.handleResize();
    jest.runOnlyPendingTimers();
    expect(spy).toBeCalled();
  });
});
<|endoftext|>


<commit_before>"use strict"
/**
 * Hey guys! I'm going to write kind of a template here that you guys
 * can fill out however you like. If you want to change function names
 * or given variable names, let me know and I will update the other
 * files to reflect the changes!
 */

/**
 * The Model is a container for a set of bodies. You'll be able to
 * manipulate them through here!
 */

var Sector = function(){
	this.bodies = [];
}

Sector.prototype.addBody = function(x,y,t,v) { // Remind Kevin to edit values
	if (t > 2)
	{
		var new_body = new Star(x,y,t,v); // Remind Kevin to put stars.
		this.bodies.push(new_body);
	}
	else if (t < 1)
	{
		var new_body = new Moon(x,y,t,v);
		this.bodies.push(new_body);
	}
	else
	{
		var new_body = new Planet(x,y,t,v);
		this.bodies.push(new_body);
	}
}
Sector.prototype.update = function(dt) {
	for (idx in Sector.bodies)
}
Sector.prototype.get_bodies = function() {
	return this.bodies;
}

Sector.prototype.collision_update = function(){
	var col_array = [[],[]];
	for (idx in Sector.bodies) {
		for (idx2 in Sector.bodies) {
			if (idx != idx2) {
				var x1 = Sector.bodies[idx].x_position;
				var x2 = Sector.bodies[idx2].x_position;
				var y1 = Sector.bodies[idx].y_position;
				var y2 = Sector.bodies[idx2].y_position; // Remind Kevin to add index.
				var x_dist = (x1-x2);
				var y_dist = (y1-y2);
				var t_dist = Math.pow(Math.pow(x_dist, 2) + Math.pow(y_dist, 2), 0.5); // ** doesn't work i guess.
				if ((Sector.bodies[idx].radius + Sector.bodies[idx2].radius) > t_dist){
					if (typeof(Sector.bodies[idx]) == Star) {
						Sector.remove(Sector.bodies[idx2]);
						var coor = (x2,y2);
						col_array[0].push(coor);
					}
					else if (typeof(Sector.bodies[idx2]) == Star){
						Sector.remove(Sector.bodies[idx]);
						var coor = (x1,y1);
						col_array[0].push(coor);
					}
					else {
						Sector.remove(Sector.bodies[idx2]);
						Sector.remove(Sector.bodies[idx]);
						var x_coor = (x1+x2)/2;
						var y_coor = (y1+y2)/2;
						var coor = (x_coor,y_coor);
						col_array[1].push(coor);
					}
				}
			}
		}
	}
	return col_array;
}

var createOrbitables = function(bodytype) {
	orbitables = [];
	if (bodytype == 'Planet') {
		for (idx in Sector.bodies) {
			if (typeof Sector.bodies[idx] == 'Star') {
				orbitables.push(Sector.bodies[idx]);
			}
		}
	}
	elseif (bodytype == 'Moon') {
		for (idx in Sector.bodies) {
			if (typeof Sector.bodies[idx] == 'Star' || typeof Sector.bodies == 'Planet') {
				orbitables.push(Sector.bodies[idx]);
			}
		}
	}
	return orbitables;
}

Sector.prototype.neighbor = function(body) {
	var dist_array = [];
	var neighbor_array = [];
	orbitables = createOrbitables(typeof body)
	for (idx in orbitables) {
		var x1 = body.x_position - Sector.bodies[idx].x_position;
		var y1 = body.y_position - Sector.bodies[idx].y_position;
		var dist = Math.pow(Math.pow(x1, 2) + Math.pow(y1, 2), 0.5);
		if (dist != 0){
			dist_array.push(dist);
			neighbor_array.push(Sector.bodies[idx]);
		}
	}
	var min_dist = math.min(dist_array);
	var n_idx = dist_array.indexOf(min_dist);
	return [neighbor_array[n_idx], x1, y1, dist];
}

// calculates the acceleration for body1 (body2 is unaffected by this acceleration)
Sector.prototype.acceleration = function(body1, body2, dist, x1, y1) {
	var magnitude = body1.mass * body2.mass / Math.pow(dist,2);
	var cos = -x1/dist;
	var sin = -y1/dist;
	return [magnitude*cos, magnitude*sin]
}

var Body = function(x, y, t, v) {
	this.x = x;
	this.y = y;
}

var Star = function(x, y, t, v) {
	Body.call(this, x, y, t, v);
	this.color = "#FFFF00";
	this.radius = 400;
}

var Planet = function(x, y, t, v) {
	Body.call(this, x, y, t, v);
	this.color = "#00FF00"
	this.radius = 20;
}

var Moon = function(x, y, t, v) {
	Body.call(this, x, y, t, v);
	this.color = "#888888";
	this.radius = 5;
}
<commit_msg>modified neighbor<commit_after>"use strict"
/**
 * Hey guys! I'm going to write kind of a template here that you guys
 * can fill out however you like. If you want to change function names
 * or given variable names, let me know and I will update the other
 * files to reflect the changes!
 */

/**
 * The Model is a container for a set of bodies. You'll be able to
 * manipulate them through here!
 */

var Sector = function(){
	this.bodies = [];
	this.planets = [];
	this.stars = []
}

Sector.prototype.addBody = function(x,y,t,v) { // Remind Kevin to edit values
	if (t > 2)
	{
		var new_body = new Star(x,y,t,v); // Remind Kevin to put stars.
		this.bodies.push(new_body);
		this.stars.push(new_body)
	}
	else if (t < 1)
	{
		var new_body = new Moon(x,y,t,v);
		this.bodies.push(new_body);
		this.planets.push(new_body);
	}
	else
	{
		var new_body = new Planet(x,y,t,v);
		this.bodies.push(new_body);
	}
}
Sector.prototype.update = function(dt) {
	for (idx in Sector.bodies)
}
Sector.prototype.get_bodies = function() {
	return this.bodies;
}

Sector.prototype.collision_update = function(){
	var col_array = [[],[]];
	for (idx in Sector.bodies) {
		for (idx2 in Sector.bodies) {
			if (idx != idx2) {
				var x1 = Sector.bodies[idx].x_position;
				var x2 = Sector.bodies[idx2].x_position;
				var y1 = Sector.bodies[idx].y_position;
				var y2 = Sector.bodies[idx2].y_position; // Remind Kevin to add index.
				var x_dist = (x1-x2);
				var y_dist = (y1-y2);
				var t_dist = Math.pow(Math.pow(x_dist, 2) + Math.pow(y_dist, 2), 0.5); // ** doesn't work i guess.
				if ((Sector.bodies[idx].radius + Sector.bodies[idx2].radius) > t_dist){
					if (typeof Sector.bodies[idx] == 'Star') {
						Sector.remove(Sector.bodies[idx2]);
						var coor = (x2,y2);
						col_array[0].push(coor);
					}
					else if (typeof Sector.bodies[idx2] == 'Star'){
						Sector.remove(Sector.bodies[idx]);
						var coor = (x1,y1);
						col_array[0].push(coor);
					}
					else {
						Sector.remove(Sector.bodies[idx2]);
						Sector.remove(Sector.bodies[idx]);
						var x_coor = (x1+x2)/2;
						var y_coor = (y1+y2)/2;
						var coor = (x_coor,y_coor);
						col_array[1].push(coor);
					}
				}
			}
		}
	}
	return col_array;
}

Sector.prototype.neighbor = function(body) {
	var dist_array = [];
	var neighbor_array = [];
	if (typeof body == 'Moon') {
		orbitables = this.stars.concat(this.planets);
	}
	elseif (typeof body == 'Planet') {
		orbitables = this.stars;
	}
	for (idx in orbitables) {
		var x1 = body.x_position - Sector.bodies[idx].x_position;
		var y1 = body.y_position - Sector.bodies[idx].y_position;
		var dist = Math.pow(Math.pow(x1, 2) + Math.pow(y1, 2), 0.5);
		if (dist != 0){
			dist_array.push(dist);
			neighbor_array.push(Sector.bodies[idx]);
		}
	}
	var min_dist = math.min(dist_array);
	var n_idx = dist_array.indexOf(min_dist);
	return [neighbor_array[n_idx], x1, y1, dist];
}

// calculates the acceleration for body1 (body2 is unaffected by this acceleration)
Sector.prototype.acceleration = function(body1, body2, dist, x1, y1) {
	var magnitude = body1.mass * body2.mass / Math.pow(dist,2);
	var cos = -x1/dist;
	var sin = -y1/dist;
	return [magnitude*cos, magnitude*sin]
}

var Body = function(x, y, t, v) {
	this.x = x;
	this.y = y;
}

var Star = function(x, y, t, v) {
	Body.call(this, x, y, t, v);
	this.color = "#FFFF00";
	this.radius = 400;
}

var Planet = function(x, y, t, v) {
	Body.call(this, x, y, t, v);
	this.color = "#00FF00"
	this.radius = 20;
}

var Moon = function(x, y, t, v) {
	Body.call(this, x, y, t, v);
	this.color = "#888888";
	this.radius = 5;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

//node.js deps
var gpio = require('gpio');
//npm deps

//app deps
const deviceModule = require('..').device;
const cmdLineProcess = require('./lib/cmdline');

//begin module
var blueLedGpio, yellowLedGpio, intervalTimer;

blueLedGpio = gpio.export(23, {
   ready: function() {
      console.log("Blue LED Ready");
      intervalTimer = setInterval(function() {
      }, 1000);
   }
});

yellowLedGpio = gpio.export(24, {
   ready: function() {
      console.log("Yellow LED Ready");
   }
});

// // Lets assume a different LED is hooked up to pin 4, the following code
// // will make that LED blink inversely with LED from pin 22
// gpio24 = gpio.export(23, {
//    ready: function() {
//       // bind to blueLedGpio's change event
//       blueLedGpio.on("change", function(val) {
//          gpio24.set(1 - val); // set gpio24 to the opposite value
//       });
//    }
// });

// // reset the headers and unexport after 10 seconds
// setTimeout(function() {
//    clearInterval(intervalTimer);          // stops the voltage cycling
//    blueLedGpio.removeAllListeners('change');   // unbinds change event
//    blueLedGpio.reset();                        // sets header to low
//    blueLedGpio.unexport();                     // unexport the header
//
//    gpio24.reset();
//    gpio24.unexport(function() {
//       // unexport takes a callback which gets fired as soon as unexporting is done
//       process.exit(); // exits your node program
//    });
// }, 10000);

function processTest(args) {
   //
   // The device module exports an MQTT instance, which will attempt
   // to connect to the AWS IoT endpoint configured in the arguments.
   // Once connected, it will emit events which our application can
   // handle.
   //
   const device = deviceModule({
      keyPath: args.privateKey,
      certPath: args.clientCert,
      caPath: args.caCert,
      clientId: args.clientId,
      region: args.region,
      baseReconnectTimeMs: args.baseReconnectTimeMs,
      keepalive: args.keepAlive,
      protocol: args.Protocol,
      port: args.Port,
      host: args.Host,
      debug: args.Debug
   });

   var timeout;
   var count = 0;
   const minimumDelay = 250;

   if (args.testMode === 1) {
      device.subscribe('topic_1');
   } else {
      device.subscribe('topic_2');
   }
   device.subscribe('led');
   if ((Math.max(args.delay, minimumDelay)) !== args.delay) {
      console.log('substituting ' + minimumDelay + 'ms delay for ' + args.delay + 'ms...');
   }
   timeout = setInterval(function() {
      count++;

      if (args.testMode === 1) {
         device.publish('topic_2', JSON.stringify({
            mode1Process: count
         }));
      } else {
         device.publish('topic_1', JSON.stringify({
            mode2Process: count
         }));
      }
   }, Math.max(args.delay, minimumDelay)); // clip to minimum

   //
   // Do a simple publish/subscribe demo based on the test-mode passed
   // in the command line arguments.  If test-mode is 1, subscribe to
   // 'topic_1' and publish to 'topic_2'; otherwise vice versa.  Publish
   // a message every four seconds.
   //
   device
      .on('connect', function() {
         console.log('connected');
      });
   device
      .on('close', function() {
         console.log('close');
      });
   device
      .on('reconnect', function() {
         console.log('reconnect');
      });
   device
      .on('offline', function() {
         console.log('offline');
      });
   device
      .on('error', function(error) {
         console.log('error', error);
      });
   device
      .on('message', function(topic, payload) {

         if(topic == "led") {
            console.log("led");
            if(payload!=null) {
               var jsonPayload = JSON.parse(payload.toString());
               if(jsonPayload.color == "yellow") {
                  yellowLedGpio.set();
                  setTimeout(function() { yellowLedGpio.reset(); }, 2000);
               }
               if(jsonPayload.color == "blue") {
                  blueLedGpio.set();
                  setTimeout(function() { blueLedGpio.reset(); }, 2000);
               }

            }
         }
         console.log('message', topic, payload.toString());
      });
}

module.exports = cmdLineProcess;

if (require.main === module) {
   cmdLineProcess('connect to the AWS IoT service and publish/subscribe to topics using MQTT, test modes 1-2',
      process.argv.slice(2), processTest);
}<commit_msg>blue button<commit_after>/*
 * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

//node.js deps
var gpio = require('gpio');
//npm deps

//app deps
const deviceModule = require('..').device;
const cmdLineProcess = require('./lib/cmdline');

//begin module
var blueLedGpio, yellowLedGpio, blueButtonGpio, intervalTimer;

blueButtonGpio = gpio.export(6, {
   ready: function() {
      console.log("Blue Button Ready");
   }
});
blueButtonGpio.read(6, function (err, value) {
   if(err) throw err;
   blueLedGpio.set();
   setTimeout(function() { blueLedGpio.reset(); }, 2000);
})

blueLedGpio = gpio.export(23, {
   ready: function() {
      console.log("Blue LED Ready");
      intervalTimer = setInterval(function() {
      }, 1000);
   }
});

yellowLedGpio = gpio.export(24, {
   ready: function() {
      console.log("Yellow LED Ready");
   }
});

// // Lets assume a different LED is hooked up to pin 4, the following code
// // will make that LED blink inversely with LED from pin 22
// gpio24 = gpio.export(23, {
//    ready: function() {
//       // bind to blueLedGpio's change event
//       blueLedGpio.on("change", function(val) {
//          gpio24.set(1 - val); // set gpio24 to the opposite value
//       });
//    }
// });

// // reset the headers and unexport after 10 seconds
// setTimeout(function() {
//    clearInterval(intervalTimer);          // stops the voltage cycling
//    blueLedGpio.removeAllListeners('change');   // unbinds change event
//    blueLedGpio.reset();                        // sets header to low
//    blueLedGpio.unexport();                     // unexport the header
//
//    gpio24.reset();
//    gpio24.unexport(function() {
//       // unexport takes a callback which gets fired as soon as unexporting is done
//       process.exit(); // exits your node program
//    });
// }, 10000);

function processTest(args) {
   //
   // The device module exports an MQTT instance, which will attempt
   // to connect to the AWS IoT endpoint configured in the arguments.
   // Once connected, it will emit events which our application can
   // handle.
   //
   const device = deviceModule({
      keyPath: args.privateKey,
      certPath: args.clientCert,
      caPath: args.caCert,
      clientId: args.clientId,
      region: args.region,
      baseReconnectTimeMs: args.baseReconnectTimeMs,
      keepalive: args.keepAlive,
      protocol: args.Protocol,
      port: args.Port,
      host: args.Host,
      debug: args.Debug
   });

   var timeout;
   var count = 0;
   const minimumDelay = 250;

   if (args.testMode === 1) {
      device.subscribe('topic_1');
   } else {
      device.subscribe('topic_2');
   }
   device.subscribe('led');
   if ((Math.max(args.delay, minimumDelay)) !== args.delay) {
      console.log('substituting ' + minimumDelay + 'ms delay for ' + args.delay + 'ms...');
   }
   timeout = setInterval(function() {
      count++;

      if (args.testMode === 1) {
         device.publish('topic_2', JSON.stringify({
            mode1Process: count
         }));
      } else {
         device.publish('topic_1', JSON.stringify({
            mode2Process: count
         }));
      }
   }, Math.max(args.delay, minimumDelay)); // clip to minimum

   //
   // Do a simple publish/subscribe demo based on the test-mode passed
   // in the command line arguments.  If test-mode is 1, subscribe to
   // 'topic_1' and publish to 'topic_2'; otherwise vice versa.  Publish
   // a message every four seconds.
   //
   device
      .on('connect', function() {
         console.log('connected');
      });
   device
      .on('close', function() {
         console.log('close');
      });
   device
      .on('reconnect', function() {
         console.log('reconnect');
      });
   device
      .on('offline', function() {
         console.log('offline');
      });
   device
      .on('error', function(error) {
         console.log('error', error);
      });
   device
      .on('message', function(topic, payload) {

         if(topic == "led") {
            console.log("led");
            if(payload!=null) {
               var jsonPayload = JSON.parse(payload.toString());
               if(jsonPayload.color == "yellow") {
                  yellowLedGpio.set();
                  setTimeout(function() { yellowLedGpio.reset(); }, 2000);
               }
               if(jsonPayload.color == "blue") {
                  blueLedGpio.set();
                  setTimeout(function() { blueLedGpio.reset(); }, 2000);
               }

            }
         }
         console.log('message', topic, payload.toString());
      });
}

module.exports = cmdLineProcess;

if (require.main === module) {
   cmdLineProcess('connect to the AWS IoT service and publish/subscribe to topics using MQTT, test modes 1-2',
      process.argv.slice(2), processTest);
}<|endoftext|>


<commit_before>// bbcode for the topoguide
(function(C2C, $) {

  var img_tag;

  // apply bbcode button
  // this is more complex than for the forums,
  // because we more complex bbcodes
  C2C.insertBbcode = function(selec, targetElm) {
    var opening_tag, closing_tag, selec_2;

    switch (selec) {
      case 'wl': // wiki link
        opening_tag = '[[|';
        closing_tag = ']]';
        selec_2 = '';
        break;
      case 'L#': // route line
        opening_tag = 'L# | ';
        closing_tag = ' |  | ';
        selec_2 = 'L# ';
        break;
      case 'url':
        opening_tag = '[url=]';
        closing_tag = '[/url]';
        selec_2 = selec;
        break;
      case 'img':
        opening_tag = '';
        closing_tag = img_tag;
        selec_2 = selec;
        break;
      default:
        opening_tag = '[' + selec + ']';
        closing_tag = '[/' + selec + ']';
        selec_2 = selec;
        break;
    }

    var e = $('#' + targetElm)[0];
    var value = e.value;

    var scrollPos = e.scrollTop;

    if ('selectionStart' in e) {

      var start = e.selectionStart;
      var end = e.selectionEnd;

      // compute new value
      e.value = value.substring(0, start) +
                opening_tag +
                value.substring(start, end) +
                closing_tag +
                value.substring(end, e.textLength);

      // be sure to put focus back
      e.scrollTop = scrollPos;
      e.focus();

      // put cursor at the end of the added bbcode caret
      var newPos;
      if (selec == 'wl' || selec == 'url' || start == end) {
        newPos = start + selec_2.length + 2;
      } else {
        newPos = end + opening_tag.length + closing_tag.length;
      }
      e.setSelectionRange(newPos, newPos);

    } else if (document.selection) { // old ie

      // check that selected text is from the textarea
      var range = document.selection.createRange();
      if (range && range.parentElement() == e && range.text.length) {
          range.text = opening_tag + range.text + closing_tag;
          range.select();
      } else {
        // enjoy
        e.focus(e.caretPos);
        e.focus(e.value.length);
        e.caretPos = document.selection.createRange().duplicate();

        var magic = "%~%";
        var orig = e.value;
        e.caretPos.text = magic;
        var i = e.value.search(magic);
        e.value = orig.substr(0, i) + opening_tag + closing_tag + orig.substr(i, e.value.length);

        var r = 0;
        for (var n = 0; n < i; n++) {
          if (/[\r]/ig.test(e.value.substr(n, 2))) {
            r++;
          }
        }

        var pos = i + 2 + selec_2.length - r;
        r = e.createTextRange();
        r.moveStart('character', pos);
        r.collapse();
        r.select();
      }
      e.focus();
    }
  };

  // expand or contract textarea height
  C2C.changeTextareaSize = function(id, up_down) {
    var textarea = $('textarea#' + id);
    var height = textarea.height();

    textarea.height(!!up_down ? height + 80 : Math.max(60, height - 80));
  };

  // image stuff

  // if custom legend option is unchecked, be sure to
  // update corresponding field value with original legend
  C2C.doUpdateImageLegend = function() {
    var custom = $('#inserted_image_customlegend').is(':checked');
    if (custom) {
      $('#inserted_image_legend').removeAttr('disabled');
    } else {
      $('#inserted_image_legend')
        .attr('disabled', 'disabled')
        .val($('.selected_image img').first().attr('alt'));
    }
  };

  // when a new image is selected in the list
  C2C.updateSelectedImage = function(img) {
    // update selected image
    var selected_class = 'selected_image';
    $('div.image').removeClass(selected_class);
    var selected = $(img).parent().parent().addClass(selected_class);

    // update legend
    C2C.doUpdateImageLegend();

    // update for id
    $('#inserted_image_id').val(selected.attr('id').substring(17));
  };

  // finally insert tag in textarea
  C2C.doInsertImgTag = function() {
    var align = $('input[name=inserted_image_alignment]:checked').last().val() || '';
    var borderlegend = $('#inserted_image_hideborderlegend').is(':checked') ? ' no_border no_legend' : '';

    // build tag
    img_tag = '[img=' + $('#inserted_image_id').val() + ' ' + align + borderlegend;
    if ($('#inserted_image_customlegend').is(':checked')) {
      img_tag += ']' + $('#inserted_image_legend').val() + '[/img]';
    } else {
      img_tag += '/]';
    }
    img_tag += "\n";

    C2C.insertBbcode('img', $('#inserted_image_div').val());
    $.modalbox.hide();
  };

  // bbcode toolbar, initiated once dom loaded
  $(function() {
    var bbcode_toolbars = $('.bbcodetoolcontainer');
    var textareas = bbcode_toolbars.next();

    // hide all bbcode toolbars on start
    bbcode_toolbars.css('visibility', 'hidden');

    // hide all toolbars except the one related to the textarea on  focus
    bbcode_toolbars.next().focus(function() {
      bbcode_toolbars.css('visibility', 'hidden');
      $(this).prev().css('visibility', 'visible');
    });
  });

})(window.C2C = window.C2C || {}, jQuery);
<commit_msg>js for sub-titles buttons in bbcode toolbar<commit_after>// bbcode for the topoguide
(function(C2C, $) {

  var img_tag;

  // apply bbcode button
  // this is more complex than for the forums,
  // because we more complex bbcodes
  C2C.insertBbcode = function(selec, targetElm) {
    var opening_tag, closing_tag, selec_2;

    switch (selec) {
      case 'h2': // sub title 2
        opening_tag = '## ';
        closing_tag = '';
        selec_2 = '#';
        break;
      case 'h3': // sub title 3
        opening_tag = '### ';
        closing_tag = '';
        selec_2 = '##';
        break;
      case 'h4': // sub title 4
        opening_tag = '#### ';
        closing_tag = '';
        selec_2 = '###';
        break;
      case 'wl': // wiki link
        opening_tag = '[[|';
        closing_tag = ']]';
        selec_2 = '';
        break;
      case 'L#': // route line
        opening_tag = 'L# | ';
        closing_tag = ' |  | ';
        selec_2 = 'L# ';
        break;
      case 'url':
        opening_tag = '[url=]';
        closing_tag = '[/url]';
        selec_2 = selec;
        break;
      case 'img':
        opening_tag = '';
        closing_tag = img_tag;
        selec_2 = selec;
        break;
      default:
        opening_tag = '[' + selec + ']';
        closing_tag = '[/' + selec + ']';
        selec_2 = selec;
        break;
    }

    var e = $('#' + targetElm)[0];
    var value = e.value;

    var scrollPos = e.scrollTop;

    if ('selectionStart' in e) {

      var start = e.selectionStart;
      var end = e.selectionEnd;

      // compute new value
      e.value = value.substring(0, start) +
                opening_tag +
                value.substring(start, end) +
                closing_tag +
                value.substring(end, e.textLength);

      // be sure to put focus back
      e.scrollTop = scrollPos;
      e.focus();

      // put cursor at the end of the added bbcode caret
      var newPos;
      if (selec == 'wl' || selec == 'url' || start == end) {
        newPos = start + selec_2.length + 2;
      } else {
        newPos = end + opening_tag.length + closing_tag.length;
      }
      e.setSelectionRange(newPos, newPos);

    } else if (document.selection) { // old ie

      // check that selected text is from the textarea
      var range = document.selection.createRange();
      if (range && range.parentElement() == e && range.text.length) {
          range.text = opening_tag + range.text + closing_tag;
          range.select();
      } else {
        // enjoy
        e.focus(e.caretPos);
        e.focus(e.value.length);
        e.caretPos = document.selection.createRange().duplicate();

        var magic = "%~%";
        var orig = e.value;
        e.caretPos.text = magic;
        var i = e.value.search(magic);
        e.value = orig.substr(0, i) + opening_tag + closing_tag + orig.substr(i, e.value.length);

        var r = 0;
        for (var n = 0; n < i; n++) {
          if (/[\r]/ig.test(e.value.substr(n, 2))) {
            r++;
          }
        }

        var pos = i + 2 + selec_2.length - r;
        r = e.createTextRange();
        r.moveStart('character', pos);
        r.collapse();
        r.select();
      }
      e.focus();
    }
  };

  // expand or contract textarea height
  C2C.changeTextareaSize = function(id, up_down) {
    var textarea = $('textarea#' + id);
    var height = textarea.height();

    textarea.height(!!up_down ? height + 80 : Math.max(60, height - 80));
  };

  // image stuff

  // if custom legend option is unchecked, be sure to
  // update corresponding field value with original legend
  C2C.doUpdateImageLegend = function() {
    var custom = $('#inserted_image_customlegend').is(':checked');
    if (custom) {
      $('#inserted_image_legend').removeAttr('disabled');
    } else {
      $('#inserted_image_legend')
        .attr('disabled', 'disabled')
        .val($('.selected_image img').first().attr('alt'));
    }
  };

  // when a new image is selected in the list
  C2C.updateSelectedImage = function(img) {
    // update selected image
    var selected_class = 'selected_image';
    $('div.image').removeClass(selected_class);
    var selected = $(img).parent().parent().addClass(selected_class);

    // update legend
    C2C.doUpdateImageLegend();

    // update for id
    $('#inserted_image_id').val(selected.attr('id').substring(17));
  };

  // finally insert tag in textarea
  C2C.doInsertImgTag = function() {
    var align = $('input[name=inserted_image_alignment]:checked').last().val() || '';
    var borderlegend = $('#inserted_image_hideborderlegend').is(':checked') ? ' no_border no_legend' : '';

    // build tag
    img_tag = '[img=' + $('#inserted_image_id').val() + ' ' + align + borderlegend;
    if ($('#inserted_image_customlegend').is(':checked')) {
      img_tag += ']' + $('#inserted_image_legend').val() + '[/img]';
    } else {
      img_tag += '/]';
    }
    img_tag += "\n";

    C2C.insertBbcode('img', $('#inserted_image_div').val());
    $.modalbox.hide();
  };

  // bbcode toolbar, initiated once dom loaded
  $(function() {
    var bbcode_toolbars = $('.bbcodetoolcontainer');
    var textareas = bbcode_toolbars.next();

    // hide all bbcode toolbars on start
    bbcode_toolbars.css('visibility', 'hidden');

    // hide all toolbars except the one related to the textarea on  focus
    bbcode_toolbars.next().focus(function() {
      bbcode_toolbars.css('visibility', 'hidden');
      $(this).prev().css('visibility', 'visible');
    });
  });

})(window.C2C = window.C2C || {}, jQuery);
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { shallow, mount } from 'enzyme';

import DayPickerInput from '../../src/DayPickerInput';
import DayPicker from '../../src/DayPicker';

describe('DayPickerInput', () => {
  describe('rendering', () => {
    it('should have default props', () => {
      const dayPicker = <DayPickerInput />;
      expect(dayPicker.props.dayPickerProps).toEqual({});
      expect(dayPicker.props.value).toBe('');
      expect(dayPicker.props.format).toBe('L');
      expect(dayPicker.props.hideOnDayClick).toBe(true);
      expect(dayPicker.props.component).toBe('input');
    });
    it('should have the right CSS classes', () => {
      const wrapper = shallow(<DayPickerInput />);
      expect(wrapper).toHaveClassName('DayPickerInput');
    });
    it('should set the month based on the specified format', () => {
      const wrapper = shallow(
        <DayPickerInput value="12/05/2010" format="DD/MM/YYYY" />
      );
      expect(wrapper.instance().state.month.getMonth()).toBe(4);
      expect(wrapper.instance().state.month.getFullYear()).toBe(2010);
    });
    it('should not set the month if the value is not valid acording to `format`', () => {
      const wrapper = shallow(
        <DayPickerInput value="12/17/2010" format="DD/MM/YYYY" />
      );
      expect(wrapper.instance().state.month).toBeUndefined();
    });
    it('should accept multiple `format`s', () => {
      const wrapper = shallow(
        <DayPickerInput
          value="2010/05/12"
          format={['DD/MM/YYYY', 'YYYY/MM/DD']}
        />
      );
      expect(wrapper.instance().state.month.getMonth()).toBe(4);
      expect(wrapper.instance().state.month.getFullYear()).toBe(2010);
    });
    it('should render an input field with the passed attributes', () => {
      const wrapper = shallow(
        <DayPickerInput value="12/14/2017" placeholder="bar" />
      );
      const input = wrapper.find('input');
      expect(input).toBeDefined();
      expect(input).toHaveProp('value', '12/14/2017');
      expect(input).toHaveProp('placeholder', 'bar');
    });
    it('should work with not value dates', () => {
      const wrapper = shallow(
        <DayPickerInput value="very wrong" placeholder="bar" />
      );
      const input = wrapper.find('input');
      expect(input).toHaveProp('value', 'very wrong');
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find(DayPicker)).toBeDefined();
    });
    it('should show the DayPicker', () => {
      const wrapper = shallow(<DayPickerInput />);
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find('.DayPickerInput-OverlayWrapper')).toBeDefined();
      expect(wrapper.find('.DayPickerInput-Overlay')).toBeDefined();
      expect(wrapper.find(DayPicker)).toBeDefined();
    });
    it('should work with custom class names', () => {
      const wrapper = shallow(
        <DayPickerInput
          classNames={{
            container: 'foo-container',
            overlayWrapper: 'foo-overlay-wrapper',
            overlay: 'foo-overlay',
          }}
        />
      );
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find('.foo-container')).toBeDefined();
      expect(wrapper.find('.foo-overlay-wrapper')).toBeDefined();
      expect(wrapper.find('.foo-overlay')).toBeDefined();
    });
    it('should hide the DayPicker', () => {
      const wrapper = shallow(<DayPickerInput />);
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find(DayPicker)).toHaveLength(1);
      wrapper.update();
      wrapper.instance().hideDayPicker();
      expect(wrapper.find('.DayPicker')).toHaveLength(0);
    });
    it('should pass props to the DayPicker', () => {
      const instance = mount(
        <DayPickerInput
          dayPickerProps={{
            enableOutsideDays: true,
            numberOfMonths: 12,
            fixedWeeks: false,
          }}
        />
      ).instance();
      instance.showDayPicker();
      expect(instance.daypicker.props.fixedWeeks).toBe(false);
      expect(instance.daypicker.props.enableOutsideDays).toBe(true);
      expect(instance.daypicker.props.numberOfMonths).toBe(12);
    });
    it('should open the daypicker to the month of the selected day', () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find('.DayPicker-Caption div').first()).toHaveText(
        'December 2017'
      );
    });
    it('should display the current value as a selected day', () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find('.DayPicker-Day--selected')).toHaveLength(1);
      expect(wrapper.find('.DayPicker-Day--selected')).toHaveText('15');
    });
    it('should update the current value when `value` prop is updated', () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.setProps({ value: '01/10/2018' });
      expect(wrapper.instance().state.value).toBe('01/10/2018');
    });
    it('should not update the current value when other props are updated', () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.setProps({ dayPickerProps: {} });
      expect(wrapper.instance().state.value).toBe('12/15/2017');
    });
    it("should update the displayed month when `dayPickerProps.month`'s month is updated", () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find('.DayPicker-Caption').first()).toHaveText(
        'December 2017'
      );
      wrapper.setProps({ dayPickerProps: { month: new Date(2017, 10) } });
      expect(wrapper.instance().state.value).toBe('12/15/2017');
      expect(wrapper.find('.DayPicker-Caption').first()).toHaveText(
        'November 2017'
      );
    });
    it("should update the displayed month when `dayPickerProps.month`'s year is updated", () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find('.DayPicker-Caption').first()).toHaveText(
        'December 2017'
      );
      wrapper.setProps({ dayPickerProps: { month: new Date(2016, 10) } });
      expect(wrapper.instance().state.value).toBe('12/15/2017');
      expect(wrapper.find('.DayPicker-Caption').first()).toHaveText(
        'November 2016'
      );
    });
    it('should not update the current value when other props are updated', () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.setProps({ dayPickerProps: {} });
      expect(wrapper.instance().state.value).toBe('12/15/2017');
    });

    it('should clear timeouts when component unmounts', () => {
      const container = document.createElement('div');
      mount(<DayPickerInput />, { attachTo: container });
      const spy = jest.spyOn(window, 'clearTimeout');
      ReactDOM.unmountComponentAtNode(container);
      expect(spy).toHaveBeenCalledTimes(2);
      spy.mockRestore();
    });
  });
});
<commit_msg>Fix test for blurTimeout<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import { shallow, mount } from 'enzyme';

import DayPickerInput from '../../src/DayPickerInput';
import DayPicker from '../../src/DayPicker';

describe('DayPickerInput', () => {
  describe('rendering', () => {
    it('should have default props', () => {
      const dayPicker = <DayPickerInput />;
      expect(dayPicker.props.dayPickerProps).toEqual({});
      expect(dayPicker.props.value).toBe('');
      expect(dayPicker.props.format).toBe('L');
      expect(dayPicker.props.hideOnDayClick).toBe(true);
      expect(dayPicker.props.component).toBe('input');
    });
    it('should have the right CSS classes', () => {
      const wrapper = shallow(<DayPickerInput />);
      expect(wrapper).toHaveClassName('DayPickerInput');
    });
    it('should set the month based on the specified format', () => {
      const wrapper = shallow(
        <DayPickerInput value="12/05/2010" format="DD/MM/YYYY" />
      );
      expect(wrapper.instance().state.month.getMonth()).toBe(4);
      expect(wrapper.instance().state.month.getFullYear()).toBe(2010);
    });
    it('should not set the month if the value is not valid acording to `format`', () => {
      const wrapper = shallow(
        <DayPickerInput value="12/17/2010" format="DD/MM/YYYY" />
      );
      expect(wrapper.instance().state.month).toBeUndefined();
    });
    it('should accept multiple `format`s', () => {
      const wrapper = shallow(
        <DayPickerInput
          value="2010/05/12"
          format={['DD/MM/YYYY', 'YYYY/MM/DD']}
        />
      );
      expect(wrapper.instance().state.month.getMonth()).toBe(4);
      expect(wrapper.instance().state.month.getFullYear()).toBe(2010);
    });
    it('should render an input field with the passed attributes', () => {
      const wrapper = shallow(
        <DayPickerInput value="12/14/2017" placeholder="bar" />
      );
      const input = wrapper.find('input');
      expect(input).toBeDefined();
      expect(input).toHaveProp('value', '12/14/2017');
      expect(input).toHaveProp('placeholder', 'bar');
    });
    it('should work with not value dates', () => {
      const wrapper = shallow(
        <DayPickerInput value="very wrong" placeholder="bar" />
      );
      const input = wrapper.find('input');
      expect(input).toHaveProp('value', 'very wrong');
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find(DayPicker)).toBeDefined();
    });
    it('should show the DayPicker', () => {
      const wrapper = shallow(<DayPickerInput />);
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find('.DayPickerInput-OverlayWrapper')).toBeDefined();
      expect(wrapper.find('.DayPickerInput-Overlay')).toBeDefined();
      expect(wrapper.find(DayPicker)).toBeDefined();
    });
    it('should work with custom class names', () => {
      const wrapper = shallow(
        <DayPickerInput
          classNames={{
            container: 'foo-container',
            overlayWrapper: 'foo-overlay-wrapper',
            overlay: 'foo-overlay',
          }}
        />
      );
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find('.foo-container')).toBeDefined();
      expect(wrapper.find('.foo-overlay-wrapper')).toBeDefined();
      expect(wrapper.find('.foo-overlay')).toBeDefined();
    });
    it('should hide the DayPicker', () => {
      const wrapper = shallow(<DayPickerInput />);
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find(DayPicker)).toHaveLength(1);
      wrapper.update();
      wrapper.instance().hideDayPicker();
      expect(wrapper.find('.DayPicker')).toHaveLength(0);
    });
    it('should pass props to the DayPicker', () => {
      const instance = mount(
        <DayPickerInput
          dayPickerProps={{
            enableOutsideDays: true,
            numberOfMonths: 12,
            fixedWeeks: false,
          }}
        />
      ).instance();
      instance.showDayPicker();
      expect(instance.daypicker.props.fixedWeeks).toBe(false);
      expect(instance.daypicker.props.enableOutsideDays).toBe(true);
      expect(instance.daypicker.props.numberOfMonths).toBe(12);
    });
    it('should open the daypicker to the month of the selected day', () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find('.DayPicker-Caption div').first()).toHaveText(
        'December 2017'
      );
    });
    it('should display the current value as a selected day', () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find('.DayPicker-Day--selected')).toHaveLength(1);
      expect(wrapper.find('.DayPicker-Day--selected')).toHaveText('15');
    });
    it('should update the current value when `value` prop is updated', () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.setProps({ value: '01/10/2018' });
      expect(wrapper.instance().state.value).toBe('01/10/2018');
    });
    it('should not update the current value when other props are updated', () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.setProps({ dayPickerProps: {} });
      expect(wrapper.instance().state.value).toBe('12/15/2017');
    });
    it("should update the displayed month when `dayPickerProps.month`'s month is updated", () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find('.DayPicker-Caption').first()).toHaveText(
        'December 2017'
      );
      wrapper.setProps({ dayPickerProps: { month: new Date(2017, 10) } });
      expect(wrapper.instance().state.value).toBe('12/15/2017');
      expect(wrapper.find('.DayPicker-Caption').first()).toHaveText(
        'November 2017'
      );
    });
    it("should update the displayed month when `dayPickerProps.month`'s year is updated", () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.instance().showDayPicker();
      wrapper.update();
      expect(wrapper.find('.DayPicker-Caption').first()).toHaveText(
        'December 2017'
      );
      wrapper.setProps({ dayPickerProps: { month: new Date(2016, 10) } });
      expect(wrapper.instance().state.value).toBe('12/15/2017');
      expect(wrapper.find('.DayPicker-Caption').first()).toHaveText(
        'November 2016'
      );
    });
    it('should not update the current value when other props are updated', () => {
      const wrapper = mount(<DayPickerInput value="12/15/2017" />);
      wrapper.setProps({ dayPickerProps: {} });
      expect(wrapper.instance().state.value).toBe('12/15/2017');
    });

    it('should clear timeouts when component unmounts', () => {
      const container = document.createElement('div');
      mount(<DayPickerInput />, { attachTo: container });
      const spy = jest.spyOn(window, 'clearTimeout');
      ReactDOM.unmountComponentAtNode(container);
      expect(spy).toHaveBeenCalledTimes(3);
      spy.mockRestore();
    });
  });
});
<|endoftext|>


<commit_before><commit_msg>bump version to 1.0.0-pre4<commit_after><|endoftext|>


<commit_before>import EventEmitter from 'events';

import htmlToElement from '../../util/htmlToElement';
import EventScheduler from './scheduler';

function createEventOutput() {
  const subscribers = [];
  const subscribe = (cb) => {
    subscribers.push(cb);
    return () => {
      subscribers.splice(subscribers.indexOf(cb), 1);
    };
  };
  const emit = (time, value) => {
    for (const subscriber of subscribers) {
      subscriber(time, value);
    }
  };
  return [subscribe, emit];
}

export default class BeatClock {
  constructor(document, audioContext) {
    const TICKS_PER_BEAT = 4;
    const divs = [
      {outName: 'gate16', divisor: 1},
      {outName: 'gate8', divisor: 2},
      {outName: 'gate4', divisor: 4},
    ];

    this.inputs = {};
    this.outputs = {};

    for (const div of divs) {
      const [subscribe, emitter] = createEventOutput();
      this.outputs[div.outName] = {type: 'gateEvent', subscribe: subscribe};
      div.emitter = emitter;
    }

    let tempo = 120;
    const MIN_TEMPO = 10;
    this.panel = htmlToElement(document, '

BeatClock
<form>Tempo <input type="number" value="' + tempo + '" min="' + MIN_TEMPO + '" style="width: 50px" />bpm</form>
');
    this.panel.querySelector('input').addEventListener('input', function(e) {
      const t = parseInt(e.target.value, 10);
      if (!isNaN(t) && (t > MIN_TEMPO)) {
        tempo = t;
      }
    }, false);

    this._scheduler = new EventScheduler(audioContext);

    let nextTickTime = audioContext.currentTime + 0.1; // start first tick a little in the future
    let nextTickNumber = 0;

    this._scheduler.start(function(e) {
      const ticksPerSec = tempo*TICKS_PER_BEAT/60.0;
      const secsPerTick = 60.0/(tempo*TICKS_PER_BEAT);

      while ((nextTickTime >= e.begin) && (nextTickTime < e.end)) {
        for (const div of divs) {
          const ticksPerDiv = div.divisor;
          const tickDuration = ticksPerDiv*secsPerTick;

          if ((nextTickNumber % ticksPerDiv) === 0) {
            div.emitter(nextTickTime, true);
            div.emitter(nextTickTime+0.5*tickDuration, false);
            // TODO: "number"/count is Math.round(tick/ticksPerDiv) if we want to export that
          }
        }

        nextTickTime += secsPerTick;
        nextTickNumber++;
      }
    });
  }

  deactivate() {
    this._scheduler.stop();
  }
}
<commit_msg>Fix condition<commit_after>import EventEmitter from 'events';

import htmlToElement from '../../util/htmlToElement';
import EventScheduler from './scheduler';

function createEventOutput() {
  const subscribers = [];
  const subscribe = (cb) => {
    subscribers.push(cb);
    return () => {
      subscribers.splice(subscribers.indexOf(cb), 1);
    };
  };
  const emit = (time, value) => {
    for (const subscriber of subscribers) {
      subscriber(time, value);
    }
  };
  return [subscribe, emit];
}

export default class BeatClock {
  constructor(document, audioContext) {
    const TICKS_PER_BEAT = 4;
    const divs = [
      {outName: 'gate16', divisor: 1},
      {outName: 'gate8', divisor: 2},
      {outName: 'gate4', divisor: 4},
    ];

    this.inputs = {};
    this.outputs = {};

    for (const div of divs) {
      const [subscribe, emitter] = createEventOutput();
      this.outputs[div.outName] = {type: 'gateEvent', subscribe: subscribe};
      div.emitter = emitter;
    }

    let tempo = 120;
    const MIN_TEMPO = 10;
    this.panel = htmlToElement(document, '

BeatClock
<form>Tempo <input type="number" value="' + tempo + '" min="' + MIN_TEMPO + '" style="width: 50px" />bpm</form>
');
    this.panel.querySelector('input').addEventListener('input', function(e) {
      const t = parseInt(e.target.value, 10);
      if (!isNaN(t) && (t > MIN_TEMPO)) {
        tempo = t;
      }
    }, false);

    this._scheduler = new EventScheduler(audioContext);

    let nextTickTime = audioContext.currentTime + 0.1; // start first tick a little in the future
    let nextTickNumber = 0;

    this._scheduler.start(function(e) {
      const ticksPerSec = tempo*TICKS_PER_BEAT/60.0;
      const secsPerTick = 60.0/(tempo*TICKS_PER_BEAT);

      while (nextTickTime < e.end) {
        for (const div of divs) {
          const ticksPerDiv = div.divisor;
          const tickDuration = ticksPerDiv*secsPerTick;

          if ((nextTickNumber % ticksPerDiv) === 0) {
            div.emitter(nextTickTime, true);
            div.emitter(nextTickTime+0.5*tickDuration, false);
            // TODO: "number"/count is Math.round(tick/ticksPerDiv) if we want to export that
          }
        }

        nextTickTime += secsPerTick;
        nextTickNumber++;
      }
    });
  }

  deactivate() {
    this._scheduler.stop();
  }
}
<|endoftext|>


<commit_before>//dailybibleverse.js

Module.register("MMM-DailyBibleVerse",{
	// Default module config.
	result: [],
	defaults: {
		// Default Bible version is ESV.
		// Change it to a version that BibleGateway.com supports.
		// https://www.biblegateway.com/usage/linking/versionslist/
		version: 'ESV'
	},

	start: function() {
		Log.info("Starting module: " + this.name);
		var self = this;

		var configuredVersion = this.config.version;

		//Do this once first
		self.sendSocketNotification('START', configuredVersion);

		//Then every hour
		setInterval(function() {
		        self.sendSocketNotification('START', configuredVersion);
    		}, 3600000); //perform every hour (3600000 milliseconds)
	},

	// Override dom generator.
	getDom: function() {
		Log.log("Updating MMM-DailyBibleVerse DOM.");

		var verse = "";
		var reference = "";

		if(this.verseOfTheDay != null && this.reference != null){
			verse = this.verseOfTheDay;
			reference = " -" + this.reference;
		}

		var wrapper = document.createElement("div");
		wrapper.className = "bright";
		wrapper.innerHTML = verse + reference;
		return wrapper;
    	},

	getScripts: function() {
	    return [
	        this.file('jquery-3.1.1.min.js'), // this file will be loaded straight from the module folder.
	    ]
	},

	socketNotificationReceived: function(notification, payload) {
		Log.log("socket received from Node Helper");
		if(notification == "BIBLE_GATEWAY_RESULT"){
			var json = payload;
			Log.log(payload);
			this.verseOfTheDay = json.votd.text;
			this.reference = json.votd.reference;

			this.updateDom();
		}
	}
});
<commit_msg>Added Feature to adjust size<commit_after>//dailybibleverse.js

Module.register("MMM-DailyBibleVerse", {
    // Default module config.
    result: [],
    defaults: {
        // Default Bible version is ESV.
        // Change it to a version that BibleGateway.com supports.
        // https://www.biblegateway.com/usage/linking/versionslist/
        version: 'ESV'
    },

    start: function() {
        Log.info("Starting module: " + this.name);
        var self = this;

        var configuredVersion = this.config.version;

        //Do this once first
        self.sendSocketNotification('START', configuredVersion);

        //Then every hour
        setInterval(function() {
                self.sendSocketNotification('START', configuredVersion);
        }, 3600000); //perform every hour (3600000 milliseconds)
    },

    // Override dom generator.
    getDom: function() {
        Log.log("Updating MMM-DailyBibleVerse DOM.");

        var verse = "";
        var reference = "";

        if(this.verseOfTheDay != null && this.reference != null){
            verse = this.verseOfTheDay;
            reference = " - " + this.reference;
        }

        var wrapper = document.createElement("div");
        switch (this.config.size) {
            case 'xsmall':
                wrapper.className = "bright xsmall";
                break;
            case 'small':
                wrapper.className = "bright small";
                break;
            case 'medium':
                wrapper.className = "bright";
                break;
            case 'large':
                wrapper.className = "bright large";
                break;
            default:
                wrapper.className = "bright";
        }
        wrapper.innerHTML = verse + reference;
        return wrapper;
        },

    getScripts: function() {
        return [
            this.file('jquery-3.1.1.min.js'), // this file will be loaded straight from the module folder.
        ]
    },

    socketNotificationReceived: function(notification, payload) {
        Log.log("socket received from Node Helper");
        if(notification == "BIBLE_GATEWAY_RESULT"){
            var json = payload;
            Log.log(payload);
            this.verseOfTheDay = json.votd.text;
            this.reference = json.votd.reference;

            this.updateDom();
        }
    }
});
<|endoftext|>


<commit_before>/* @flow */
/* eslint-disable global-require */

import fs from 'fs'
import path from 'path'
import { it, wait } from 'jasmine-fix'

describe('Main Module', function() {
  // Atom sets the path to a random one, so when we install using APM, tests fail.
  // We add the real one to make the tests work.
  atom.packages.packageDirPaths.push(
    path.join(process.env.ATOM_HOME || path.join(fs.getHomeDirectory(), '.atom'), 'packages'),
  )

  function uninstallPackage(name) {
    return atom.packages.uninstallDirectory(path.join(atom.packages.getPackageDirPaths().pop(), name))
  }
  function getPackage(name) {
    // eslint-disable-next-line import/no-dynamic-require
    return require(`./fixtures/packages/${name}`)
  }

  it('works as a whole', async function() {
    const _ = atom.packages.getLoadedPackage
    const packageName = 'hydrogen'
    spyOn(atom.packages, 'getLoadedPackage').andCallFake(function(name) {
      if (name === 'some-package') {
        return {
          metadata: {
            main: 'index.js',
            'package-deps': [packageName],
          },
        }
      }
      return _.call(this, name)
    })

    expect(atom.packages.getActivePackage(packageName)).not.toBeDefined()
    await getPackage('some-package').activate()
    expect(atom.packages.getActivePackage(packageName)).toBeDefined()
    await uninstallPackage(packageName)

    const notifications = atom.notifications.getNotifications()
    expect(notifications.length).toBe(2)
    expect(notifications[0].type).toBe('info')
  })

  it('handles errors pretty good', async function() {
    const _ = atom.packages.getLoadedPackage
    spyOn(atom.packages, 'getLoadedPackage').andCallFake(function(name) {
      if (name === 'some-package') {
        return {
          metadata: {
            main: 'index.js',
            'package-deps': ['non-existent-package'],
          },
        }
      }
      return _.call(this, name)
    })

    await getPackage('some-package').activate()
    await wait(50)

    const notifications = atom.notifications.getNotifications()
    expect(notifications.length).toBe(2)
    expect(notifications[1].type).toBe('warning')
  })

  it('can install multiple packages at once', async function() {
    const _ = atom.packages.getLoadedPackage
    const packageNameFirst = 'scroll-through-time'
    const packageNameSecond = 'glow'
    spyOn(atom.packages, 'getLoadedPackage').andCallFake(function(name) {
      if (name === 'some-package') {
        return {
          metadata: {
            main: 'index.js',
            'package-deps': [packageNameFirst, packageNameSecond, 'tree-view'],
          },
        }
      }
      return _.call(this, name)
    })

    expect(atom.packages.getActivePackage(packageNameFirst)).not.toBeDefined()
    expect(atom.packages.getActivePackage(packageNameSecond)).not.toBeDefined()
    await getPackage('some-package').activate()
    expect(atom.packages.getActivePackage(packageNameFirst)).toBeDefined()
    expect(atom.packages.getActivePackage(packageNameSecond)).toBeDefined()
    await uninstallPackage(packageNameFirst)
    await uninstallPackage(packageNameSecond)

    const notifications = atom.notifications.getNotifications()
    expect(notifications.length).toBe(2)
    expect(notifications[0].type).toBe('info')
  })

  it('works with hardcoded package names', async function() {
    const _ = atom.packages.getLoadedPackage
    const packageName = 'hey-pane'
    spyOn(atom.packages, 'getLoadedPackage').andCallFake(function(name) {
      if (name === 'some-package') {
        return {
          metadata: {
            main: 'index.js',
            'package-deps': [packageName],
          },
        }
      }
      return _.call(this, name)
    })

    expect(atom.packages.getActivePackage(packageName)).not.toBeDefined()
    await getPackage('some-package').activate()
    expect(atom.packages.getActivePackage(packageName)).toBeDefined()
    await uninstallPackage(packageName)

    const notifications = atom.notifications.getNotifications()
    expect(notifications.length).toBe(2)
    expect(notifications[0].type).toBe('info')
  })

  it('stays silent when that package name is not found in active packages', async function() {
    await getPackage('some-package').activate()
    const notifications = atom.notifications.getNotifications()
    expect(notifications.length).toBe(0)
  })
})
<commit_msg>:art: Bump timeout also add some dev logging<commit_after>/* @flow */
/* eslint-disable global-require */

import fs from 'fs'
import path from 'path'
import { it, wait } from 'jasmine-fix'

describe('Main Module', function() {
  // Atom sets the path to a random one, so when we install using APM, tests fail.
  // We add the real one to make the tests work.
  atom.packages.packageDirPaths.push(
    path.join(process.env.ATOM_HOME || path.join(fs.getHomeDirectory(), '.atom'), 'packages'),
  )
  // The default timeout of 6 seconds is quite often too slow, bump it to 100 seconds
  jasmine.getEnv().defaultTimeoutInterval = 100 * 1000

  function uninstallPackage(name) {
    return atom.packages.uninstallDirectory(path.join(atom.packages.getPackageDirPaths().pop(), name))
  }
  function getPackage(name) {
    // eslint-disable-next-line import/no-dynamic-require
    return require(`./fixtures/packages/${name}`)
  }

  it('works as a whole', async function() {
    const _ = atom.packages.getLoadedPackage
    const packageName = 'hydrogen'
    spyOn(atom.packages, 'getLoadedPackage').andCallFake(function(name) {
      if (name === 'some-package') {
        return {
          metadata: {
            main: 'index.js',
            'package-deps': [packageName],
          },
        }
      }
      return _.call(this, name)
    })

    expect(atom.packages.getActivePackage(packageName)).not.toBeDefined()
    await getPackage('some-package').activate()
    expect(atom.packages.getActivePackage(packageName)).toBeDefined()
    await uninstallPackage(packageName)

    const notifications = atom.notifications.getNotifications()
    expect(notifications.length).toBe(2)
    expect(notifications[0].type).toBe('info')
  })

  it('handles errors pretty good', async function() {
    const _ = atom.packages.getLoadedPackage
    spyOn(atom.packages, 'getLoadedPackage').andCallFake(function(name) {
      if (name === 'some-package') {
        return {
          metadata: {
            main: 'index.js',
            'package-deps': ['non-existent-package'],
          },
        }
      }
      return _.call(this, name)
    })

    await getPackage('some-package').activate()
    await wait(50)

    const notifications = atom.notifications.getNotifications()
    console.log('notifications', notifications)
    expect(notifications.length).toBe(2)
    expect(notifications[1].type).toBe('warning')
  })

  it('can install multiple packages at once', async function() {
    const _ = atom.packages.getLoadedPackage
    const packageNameFirst = 'scroll-through-time'
    const packageNameSecond = 'glow'
    spyOn(atom.packages, 'getLoadedPackage').andCallFake(function(name) {
      if (name === 'some-package') {
        return {
          metadata: {
            main: 'index.js',
            'package-deps': [packageNameFirst, packageNameSecond, 'tree-view'],
          },
        }
      }
      return _.call(this, name)
    })

    expect(atom.packages.getActivePackage(packageNameFirst)).not.toBeDefined()
    expect(atom.packages.getActivePackage(packageNameSecond)).not.toBeDefined()
    await getPackage('some-package').activate()
    expect(atom.packages.getActivePackage(packageNameFirst)).toBeDefined()
    expect(atom.packages.getActivePackage(packageNameSecond)).toBeDefined()
    await uninstallPackage(packageNameFirst)
    await uninstallPackage(packageNameSecond)

    const notifications = atom.notifications.getNotifications()
    expect(notifications.length).toBe(2)
    expect(notifications[0].type).toBe('info')
  })

  it('works with hardcoded package names', async function() {
    const _ = atom.packages.getLoadedPackage
    const packageName = 'hey-pane'
    spyOn(atom.packages, 'getLoadedPackage').andCallFake(function(name) {
      if (name === 'some-package') {
        return {
          metadata: {
            main: 'index.js',
            'package-deps': [packageName],
          },
        }
      }
      return _.call(this, name)
    })

    expect(atom.packages.getActivePackage(packageName)).not.toBeDefined()
    await getPackage('some-package').activate()
    expect(atom.packages.getActivePackage(packageName)).toBeDefined()
    await uninstallPackage(packageName)

    const notifications = atom.notifications.getNotifications()
    expect(notifications.length).toBe(2)
    expect(notifications[0].type).toBe('info')
  })

  it('stays silent when that package name is not found in active packages', async function() {
    await getPackage('some-package').activate()
    const notifications = atom.notifications.getNotifications()
    expect(notifications.length).toBe(0)
  })
})
<|endoftext|>


<commit_before>const discogService = require('./discog-service')

exports.home = (req, res) => {
  res.render('home')
}

exports.search = (req, res) => {
  const q = req.query.q
  const page = req.query.page ? req.query.page : 1
  const options = {type: ['artist'], page, per_page: 10}

  res.locals.db.search(q, options).then((data) => {
    res.render('results', {data, q, page} )
  })
}

exports.getReleaseDetails = (req, res) => {
  const id = req.params.id

  res.locals.db.getRelease(id).then((data) => {
    res.render('release', {'data': data} )
  })
}

exports.getMasterDetails = (req, res) => {
  const id = req.params.id

  res.locals.db.getMaster(id).then((data) => {
    res.render('master', {'data': data, 'images': data.images})
  })

}

exports.getArtistDetails = (req, res) => {
  const {id} = req.params
  const getArtist = discogService.getArtist(res, id)

  discogService.getArtist(res, id).then( (data) => {
    const {id} = data

    discogService.getArtistReleases(res, id).then( (releaseData) => {
      const {images, members} = data
      const {releases} = releaseData
      res.render('artist', {
        data,
        images,
        members,
        releases
      })
    })
  })
}<commit_msg>removed unnecessary const<commit_after>const discogService = require('./discog-service')

exports.home = (req, res) => {
  res.render('home')
}

exports.search = (req, res) => {
  const q = req.query.q
  const page = req.query.page ? req.query.page : 1
  const options = {type: ['artist'], page, per_page: 10}

  res.locals.db.search(q, options).then((data) => {
    res.render('results', {data, q, page} )
  })
}

exports.getReleaseDetails = (req, res) => {
  const id = req.params.id

  res.locals.db.getRelease(id).then((data) => {
    res.render('release', {'data': data} )
  })
}

exports.getMasterDetails = (req, res) => {
  const id = req.params.id

  res.locals.db.getMaster(id).then((data) => {
    res.render('master', {'data': data, 'images': data.images})
  })

}

exports.getArtistDetails = (req, res) => {
  const {id} = req.params

  discogService.getArtist(res, id).then( (data) => {
    const {id} = data

    discogService.getArtistReleases(res, id).then( (releaseData) => {
      const {images, members} = data
      const {releases} = releaseData
      res.render('artist', {
        data,
        images,
        members,
        releases
      })
    })
  })
}<|endoftext|>


<commit_before>import chai from '@/chai';

import defaultTheme from './defaultTheme';
import { theme } from './theme';

describe('theme', () => {
  it('should set the default theme if a custom theme is not provided', () => {
    chai.expect(theme()).to.eql(defaultTheme);
  });

  describe('overriding the default theme', () => {
    it('should not override theme if theme name is not "flexa"', () => {
      const customTheme = {
        theme: {
          grista: { columns: 16 },
        },
      };

      chai.expect(theme(customTheme)).to.eql(defaultTheme);
      chai.expect(theme(customTheme).columns).to.not.eql(16);
    });

    it('should only override what is passed in', () => {
      const customTheme = {
        theme: {
          flexa: { columns: 16 },
        },
      };

      chai.expect(theme(customTheme).columns).to.eql(16);
      chai.expect(theme(customTheme)).to.not.eql(defaultTheme);
    });

    it('should override whole theme if passed', () => {
      const customTheme = {
        theme: {
          flexa: {
            breakpoints: { lg: 65, md: 55, sm: 45, xs: 35 },
            columns: 10,
            gutter: { lg: 4, md: 3, sm: 2, xs: 1 },
          },
        },
      };

      chai.expect(theme(customTheme)).to.eql(customTheme.theme.flexa);
      chai.expect(theme(customTheme)).to.not.eql(defaultTheme);
    });
  });
});
<commit_msg>test: testing entire outcome not just parts of object (#11)<commit_after>import chai from '@/chai';

import defaultTheme from './defaultTheme';
import { theme } from './theme';

describe('theme', () => {
  it('should set the default theme if a custom theme is not provided', () => {
    chai.expect(theme()).to.eql(defaultTheme);
  });

  describe('overriding the default theme', () => {
    it('should not override theme if theme name is not "flexa"', () => {
      const customTheme = {
        theme: {
          grista: { columns: 16 },
        },
      };

      chai.expect(theme(customTheme)).to.eql(defaultTheme);
      chai.expect(theme(customTheme).columns).to.not.eql(16);
    });

    it('should only override values that have been passed in', () => {
      const customTheme = {
        theme: {
          flexa: { columns: 16 },
        },
      };

      const endTheme = {
        breakpoints: { lg: 60, md: 48, sm: 30, xs: 0 },
        columns: 16,
        gutter: { lg: 2, md: 2, sm: 1, xs: 1 },
      };

      chai.expect(theme(customTheme)).to.eql(endTheme);
      chai.expect(theme(customTheme)).to.not.eql(defaultTheme);
    });

    it('should override whole theme if passed', () => {
      const customTheme = {
        theme: {
          flexa: {
            breakpoints: { lg: 65, md: 55, sm: 45, xs: 35 },
            columns: 10,
            gutter: { lg: 4, md: 3, sm: 2, xs: 1 },
          },
        },
      };

      chai.expect(theme(customTheme)).to.eql(customTheme.theme.flexa);
      chai.expect(theme(customTheme)).to.not.eql(defaultTheme);
    });
  });
});
<|endoftext|>


<commit_before>require('es6-promise').polyfill();
// require('./pubnub');
const RingCentral = require('ringcentral');
const fetchMock = require('fetch-mock');

const dialingPlanBody = require('./data/dialingPlan');
const extensionBody = require('./data/extensionInfo');
const extensionListBody = require('./data/extension');
const accountBody = require('./data/accountInfo');
const subscriptionBody = require('./data/subscription');
const apiInfoBody = require('./data/subscription');
const messageSyncBody = require('./data/messageSync');
const authzProfileBody = require('./data/authzProfile');
const blockedNumberBody = require('./data/blockedNumber');
const forwardingNumberBody = require('./data/forwardingNumber');
const phoneNumberBody = require('./data/phoneNumber');
const accountPhoneNumberBody = require('./data/accountPhoneNumber');
const presenceBody = require('./data/presence.json');
const numberParserBody = require('./data/numberParser.json');
const smsBody = require('./data/sms.json');
const ringOutBody = require('./data/ringOut.json');
const messageStoreBody = require('./data/messageStore.json');
const addressBookBody = require('./data/addressBook.json');
const callLogBody = require('./data/callLog.json');
const deviceBody = require('./data/device.json');
const conferencingBody = require('./data/conferencing.json');
const activeCallsBody = require('./data/activeCalls.json');
const meetingBody = require('./data/meeting.json');
const serviceInfoBody = require('./data/serviceInfo.json');

const mockServer = 'http://whatever';
export function createSDK(options = {}) {
  const opts = {
    ...options,
    appKey: 'test key',
    appSecret: 'test secret',
    server: mockServer,
    Request: fetchMock.constructor.Request,
    Response: fetchMock.constructor.Response,
    Headers: fetchMock.constructor.Headers,
    fetch: fetchMock.fetchMock.bind(fetchMock),
    refreshDelayMs: 1,
    redirectUri: 'http://foo',
    cachePrefix: 'sdkPrefix',
  };
  return new RingCentral(opts);
}

export function mockApi({
  method = 'GET',
  path,
  server = mockServer,
  url,
  body = {},
  status = 200,
  statusText = 'OK',
  headers,
  isOnce = true,
}) {
  let responseHeaders;
  const isJson = typeof body !== 'string';
  if (isJson && !headers) {
    responseHeaders = { 'Content-Type': 'application/json' };
  } else {
    responseHeaders = headers;
  }
  let mockUrl;
  if (url) {
    mockUrl = url;
  } else {
    mockUrl = `${server}${path}`;
  }
  const mock = isOnce ? fetchMock.once.bind(fetchMock) : fetchMock.mock.bind(fetchMock);
  mock(mockUrl, {
    body: isJson ? JSON.stringify(body) : body,
    status,
    statusText,
    headers: responseHeaders,
    sendAsJson: false
  }, {
    method,
    times: isOnce ? 1 : 20,
  });
}

export function authentication() {
  mockApi({
    method: 'POST',
    path: '/restapi/oauth/token',
    body: {
      access_token: 'ACCESS_TOKEN',
      token_type: 'bearer',
      expires_in: 3600,
      refresh_token: 'REFRESH_TOKEN',
      refresh_token_expires_in: 60480,
      scope: 'SMS RCM Foo Boo',
      expireTime: new Date().getTime() + 3600000,
      owner_id: '23231231"',
      endpoint_id: '3213213131',
    }
  });
}

export function logout() {
  mockApi({
    method: 'POST',
    path: '/restapi/oauth/revoke',
    isOnce: false,
  });
}

export function tokenRefresh(failure) {
  if (!failure) {
    mockApi({
      method: 'POST',
      path: '/restapi/oauth/token',
      body: {
        access_token: 'ACCESS_TOKEN_FROM_REFRESH',
        token_type: 'bearer',
        expires_in: 3600,
        refresh_token: 'REFRESH_TOKEN_FROM_REFRESH',
        refresh_token_expires_in: 60480,
        scope: 'SMS RCM Foo Boo'
      }
    });
  } else {
    mockApi({
      method: 'POST',
      path: '/restapi/oauth/token',
      body: {
        message: 'Wrong token',
        error_description: 'Wrong token',
        description: 'Wrong token'
      },
      status: 400,
    });
  }
}

export function presence(id) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/${id}/presence`,
    body: {
      uri: `https://platform.ringcentral.com/restapi/v1.0/account/123/extension/${id}/presence`,
      extension: {
        uri: `https://platform.ringcentral.com/restapi/v1.0/account/123/extension/${id}`,
        extensionNumber: '101',
        id,
      },
      activeCalls: [],
      presenceStatus: 'Available',
      telephonyStatus: 'Ringing',
      userStatus: 'Available',
      dndStatus: 'TakeAllCalls',
      extensionId: id
    }
  });
}

export function presenceUpdate(id, mockResponse = {}) {
  mockApi({
    path: `/restapi/v1.0/account/~/extension/${id}/presence`,
    method: 'PUT',
    body: {
      ...presenceBody,
      ...mockResponse,
    }
  });
}

export function dialingPlan(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0/account/~/dialing-plan?perPage=MAX&page=1',
    body: {
      ...dialingPlanBody,
      ...mockResponse,
    }
  });
}

export function extensionInfo(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0/account/~/extension/~',
    body: {
      ...extensionBody,
      ...mockResponse,
    },
    isOnce: false,
  });
}

export function extensionList(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension?`,
    body: {
      ...extensionListBody,
      ...mockResponse,
    }
  });
}

export function accountInfo(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0/account/~',
    body: {
      ...accountBody,
      ...mockResponse,
    }
  });
}

export function apiInfo(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0',
    body: {
      ...apiInfoBody,
      ...mockResponse,
    }
  });
}

export function messageSync(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/message-sync`,
    body: {
      ...messageSyncBody,
      ...mockResponse,
    }
  });
}

export function updateMessageStatus(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/message-store`,
    method: 'PUT',
    body: {
      ...messageStoreBody,
      ...mockResponse,
    }
  });
}

export function authzProfile(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0/account/~/extension/~/authz-profile',
    body: {
      ...authzProfileBody,
      ...mockResponse,
    }
  });
}

export function blockedNumber(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0/account/~/extension/~/blocked-number',
    body: {
      ...blockedNumberBody,
      ...mockResponse,
    }
  });
}

export function forwardingNumber(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/forwarding-number`,
    body: {
      ...forwardingNumberBody,
      ...mockResponse
    }
  });
}

export function phoneNumber(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/phone-number`,
    body: {
      ...phoneNumberBody,
      ...mockResponse,
    }
  });
}

export function accountPhoneNumber(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/phone-number`,
    body: {
      ...accountPhoneNumberBody,
      ...mockResponse,
    },
    isOnce: false
  });
}

export function subscription(mockResponse = {}) {
  mockApi({
    method: 'POST',
    url: `begin:${mockServer}/restapi/v1.0/subscription`,
    body: {
      ...subscriptionBody,
      ...mockResponse,
    },
    isOnce: false
  });
  mockApi({
    method: 'PUT',
    url: `begin:${mockServer}/restapi/v1.0/subscription`,
    body: {
      ...subscriptionBody,
      ...mockResponse,
    },
    isOnce: false
  });
  mockApi({
    method: 'DELETE',
    url: `begin:${mockServer}/restapi/v1.0/subscription`,
    body: {
      ...subscriptionBody,
      ...mockResponse,
    },
    isOnce: false
  });
}

export function numberParser(mockResponse = {}) {
  mockApi({
    method: 'POST',
    url: `begin:${mockServer}/restapi/v1.0/number-parser/`,
    body: {
      ...numberParserBody,
      ...mockResponse,
    }
  });
}

export function sms(mockResponse = {}) {
  mockApi({
    method: 'POST',
    path: '/restapi/v1.0/account/~/extension/~/sms',
    body: {
      ...smsBody,
      ...mockResponse,
    }
  });
}
export function addressBook(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/address-book-sync`,
    body: {
      ...addressBookBody,
      ...{
        syncInfo: {
          syncType: addressBookBody.syncType,
          syncToken: addressBookBody.syncToken,
          syncTime: ((new Date(Date.now() + 24 * 60 * 60 * 1000))).toISOString()
        }
      },
      ...mockResponse,
    },
    isOnce: false,
  });
}

export function callLog(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/call-log-sync`,
    body: {
      ...callLogBody,
      ...{
        syncInfo: {
          syncType: callLogBody.syncType,
          syncToken: callLogBody.syncToken,
          syncTime: ((new Date(Date.now() + 24 * 60 * 60 * 1000))).toISOString()
        }
      },
      ...mockResponse,
    },
    isOnce: false,
  });
}

export function device(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/device`,
    body: {
      ...deviceBody,
      ...mockResponse,
    }
  });
}

export function conferencing(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0/account/~/extension/~/conferencing',
    body: {
      ...conferencingBody,
      ...mockResponse,
    }
  });
}

export function activeCalls(mockResponse = {}) {
  mockApi({
    method: 'GET',
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/active-calls`,
    body: {
      ...activeCallsBody,
      ...mockResponse,
    }
  });
}

export function restore() {
  fetchMock.restore();
}

export function mockForbidden({
  method = 'GET',
  path,
  url,
  body = ''
}) {
  mockApi({
    method,
    path,
    body,
    url,
    status: 403,
  });
}

export function mockClient(client) {
  client.service = createSDK({});
}

export function ringOut(mockResponse = {}) {
  mockApi({
    isOnce: false,
    method: 'POST',
    url: `${mockServer}/restapi/v1.0/account/~/extension/~/ring-out`,
    body: {
      ...ringOutBody,
      ...mockResponse,
    }
  });
}

export function ringOutUpdate(mockResponse = {}) {
  mockApi({
    isOnce: false,
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/ring-out/`,
    body: {
      ...ringOutBody,
      ...mockResponse,
    }
  });
}
export function meeting(mockResponse = {}, meetingType = 'NoneRecurring') {
  mockApi({
    isOnce: false,
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/meeting/`,
    body: {
      ...meetingBody[meetingType],
      ...mockResponse,
    }
  });
}
export function serviceInfo(mockResponse = {}) {
  mockApi({
    isOnce: false,
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/service-info/`,
    body: {
      ...serviceInfoBody,
      ...mockResponse,
    }
  });
}

export function mockForLogin({
  mockAuthzProfile = true,
  mockExtensionInfo = true,
  mockForwardingNumber = true,
  mockMessageSync = true,
  mockConferencing = true,
  mockActiveCalls = true
} = {}) {
  authentication();
  logout();
  tokenRefresh();
  presence('~');
  dialingPlan();
  if (mockExtensionInfo) {
    extensionInfo();
  }
  accountInfo();
  apiInfo();
  if (mockAuthzProfile) {
    authzProfile();
  }
  device();
  extensionList();
  accountPhoneNumber();
  blockedNumber();
  if (mockForwardingNumber) {
    forwardingNumber();
  }
  if (mockMessageSync) {
    messageSync();
  }
  phoneNumber();
  subscription();
  callLog();
  addressBook();
  if (mockConferencing) {
    conferencing();
  }
  if (mockActiveCalls) {
    activeCalls();
  }
}

<commit_msg>Modify mockApi to specify http method name<commit_after>require('es6-promise').polyfill();
// require('./pubnub');
const RingCentral = require('ringcentral');
const fetchMock = require('fetch-mock');

const dialingPlanBody = require('./data/dialingPlan');
const extensionBody = require('./data/extensionInfo');
const extensionListBody = require('./data/extension');
const accountBody = require('./data/accountInfo');
const subscriptionBody = require('./data/subscription');
const apiInfoBody = require('./data/subscription');
const messageSyncBody = require('./data/messageSync');
const authzProfileBody = require('./data/authzProfile');
const blockedNumberBody = require('./data/blockedNumber');
const forwardingNumberBody = require('./data/forwardingNumber');
const phoneNumberBody = require('./data/phoneNumber');
const accountPhoneNumberBody = require('./data/accountPhoneNumber');
const presenceBody = require('./data/presence.json');
const numberParserBody = require('./data/numberParser.json');
const smsBody = require('./data/sms.json');
const ringOutBody = require('./data/ringOut.json');
const messageStoreBody = require('./data/messageStore.json');
const addressBookBody = require('./data/addressBook.json');
const callLogBody = require('./data/callLog.json');
const deviceBody = require('./data/device.json');
const conferencingBody = require('./data/conferencing.json');
const activeCallsBody = require('./data/activeCalls.json');
const meetingBody = require('./data/meeting.json');
const serviceInfoBody = require('./data/serviceInfo.json');

const mockServer = 'http://whatever';
export function createSDK(options = {}) {
  const opts = {
    ...options,
    appKey: 'test key',
    appSecret: 'test secret',
    server: mockServer,
    Request: fetchMock.constructor.Request,
    Response: fetchMock.constructor.Response,
    Headers: fetchMock.constructor.Headers,
    fetch: fetchMock.fetchMock.bind(fetchMock),
    refreshDelayMs: 1,
    redirectUri: 'http://foo',
    cachePrefix: 'sdkPrefix',
  };
  return new RingCentral(opts);
}

export function mockApi({
  method = 'GET',
  path,
  server = mockServer,
  url,
  body = {},
  status = 200,
  statusText = 'OK',
  headers,
  isOnce = true,
}) {
  let responseHeaders;
  const isJson = typeof body !== 'string';
  if (isJson && !headers) {
    responseHeaders = { 'Content-Type': 'application/json' };
  } else {
    responseHeaders = headers;
  }
  let mockUrl;
  if (url) {
    mockUrl = url;
  } else {
    mockUrl = `${server}${path}`;
  }
  const mock = isOnce ? fetchMock.once.bind(fetchMock) : fetchMock.mock.bind(fetchMock);
  mock(mockUrl, {
    body: isJson ? JSON.stringify(body) : body,
    status,
    statusText,
    headers: responseHeaders,
    sendAsJson: false
  }, {
    method,
    times: isOnce ? 1 : 20,
  });
}

export function authentication() {
  mockApi({
    method: 'POST',
    path: '/restapi/oauth/token',
    body: {
      access_token: 'ACCESS_TOKEN',
      token_type: 'bearer',
      expires_in: 3600,
      refresh_token: 'REFRESH_TOKEN',
      refresh_token_expires_in: 60480,
      scope: 'SMS RCM Foo Boo',
      expireTime: new Date().getTime() + 3600000,
      owner_id: '23231231"',
      endpoint_id: '3213213131',
    }
  });
}

export function logout() {
  mockApi({
    method: 'POST',
    path: '/restapi/oauth/revoke',
    isOnce: false,
  });
}

export function tokenRefresh(failure) {
  if (!failure) {
    mockApi({
      method: 'POST',
      path: '/restapi/oauth/token',
      body: {
        access_token: 'ACCESS_TOKEN_FROM_REFRESH',
        token_type: 'bearer',
        expires_in: 3600,
        refresh_token: 'REFRESH_TOKEN_FROM_REFRESH',
        refresh_token_expires_in: 60480,
        scope: 'SMS RCM Foo Boo'
      }
    });
  } else {
    mockApi({
      method: 'POST',
      path: '/restapi/oauth/token',
      body: {
        message: 'Wrong token',
        error_description: 'Wrong token',
        description: 'Wrong token'
      },
      status: 400,
    });
  }
}

export function presence(id) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/${id}/presence`,
    body: {
      uri: `https://platform.ringcentral.com/restapi/v1.0/account/123/extension/${id}/presence`,
      extension: {
        uri: `https://platform.ringcentral.com/restapi/v1.0/account/123/extension/${id}`,
        extensionNumber: '101',
        id,
      },
      activeCalls: [],
      presenceStatus: 'Available',
      telephonyStatus: 'Ringing',
      userStatus: 'Available',
      dndStatus: 'TakeAllCalls',
      extensionId: id
    }
  });
}

export function presenceUpdate(id, mockResponse = {}) {
  mockApi({
    path: `/restapi/v1.0/account/~/extension/${id}/presence`,
    method: 'PUT',
    body: {
      ...presenceBody,
      ...mockResponse,
    }
  });
}

export function dialingPlan(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0/account/~/dialing-plan?perPage=MAX&page=1',
    body: {
      ...dialingPlanBody,
      ...mockResponse,
    }
  });
}

export function extensionInfo(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0/account/~/extension/~',
    body: {
      ...extensionBody,
      ...mockResponse,
    },
    isOnce: false,
  });
}

export function extensionList(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension?`,
    body: {
      ...extensionListBody,
      ...mockResponse,
    }
  });
}

export function accountInfo(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0/account/~',
    body: {
      ...accountBody,
      ...mockResponse,
    }
  });
}

export function apiInfo(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0',
    body: {
      ...apiInfoBody,
      ...mockResponse,
    }
  });
}

export function messageSync(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/message-sync`,
    body: {
      ...messageSyncBody,
      ...mockResponse,
    }
  });
}

export function updateMessageStatus(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/message-store`,
    method: 'PUT',
    body: {
      ...messageStoreBody,
      ...mockResponse,
    }
  });
}

export function authzProfile(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0/account/~/extension/~/authz-profile',
    body: {
      ...authzProfileBody,
      ...mockResponse,
    }
  });
}

export function blockedNumber(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0/account/~/extension/~/blocked-number',
    body: {
      ...blockedNumberBody,
      ...mockResponse,
    }
  });
}

export function forwardingNumber(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/forwarding-number`,
    body: {
      ...forwardingNumberBody,
      ...mockResponse
    }
  });
}

export function phoneNumber(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/phone-number`,
    body: {
      ...phoneNumberBody,
      ...mockResponse,
    }
  });
}

export function accountPhoneNumber(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/phone-number`,
    body: {
      ...accountPhoneNumberBody,
      ...mockResponse,
    },
    isOnce: false
  });
}

export function subscription(mockResponse = {}) {
  mockApi({
    method: 'POST',
    url: `begin:${mockServer}/restapi/v1.0/subscription`,
    body: {
      ...subscriptionBody,
      ...mockResponse,
    },
    isOnce: false
  });
  mockApi({
    method: 'PUT',
    url: `begin:${mockServer}/restapi/v1.0/subscription`,
    body: {
      ...subscriptionBody,
      ...mockResponse,
    },
    isOnce: false
  });
  mockApi({
    method: 'DELETE',
    url: `begin:${mockServer}/restapi/v1.0/subscription`,
    body: {
      ...subscriptionBody,
      ...mockResponse,
    },
    isOnce: false
  });
}

export function numberParser(mockResponse = {}) {
  mockApi({
    method: 'POST',
    url: `begin:${mockServer}/restapi/v1.0/number-parser/`,
    body: {
      ...numberParserBody,
      ...mockResponse,
    }
  });
}

export function sms(mockResponse = {}) {
  mockApi({
    method: 'POST',
    path: '/restapi/v1.0/account/~/extension/~/sms',
    body: {
      ...smsBody,
      ...mockResponse,
    }
  });
}
export function addressBook(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/address-book-sync`,
    body: {
      ...addressBookBody,
      ...{
        syncInfo: {
          syncType: addressBookBody.syncType,
          syncToken: addressBookBody.syncToken,
          syncTime: ((new Date(Date.now() + 24 * 60 * 60 * 1000))).toISOString()
        }
      },
      ...mockResponse,
    },
    isOnce: false,
  });
}

export function callLog(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/call-log-sync`,
    body: {
      ...callLogBody,
      ...{
        syncInfo: {
          syncType: callLogBody.syncType,
          syncToken: callLogBody.syncToken,
          syncTime: ((new Date(Date.now() + 24 * 60 * 60 * 1000))).toISOString()
        }
      },
      ...mockResponse,
    },
    isOnce: false,
  });
}

export function device(mockResponse = {}) {
  mockApi({
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/device`,
    body: {
      ...deviceBody,
      ...mockResponse,
    }
  });
}

export function conferencing(mockResponse = {}) {
  mockApi({
    path: '/restapi/v1.0/account/~/extension/~/conferencing',
    body: {
      ...conferencingBody,
      ...mockResponse,
    }
  });
}

export function activeCalls(mockResponse = {}) {
  mockApi({
    method: 'GET',
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/active-calls`,
    body: {
      ...activeCallsBody,
      ...mockResponse,
    }
  });
}

export function restore() {
  fetchMock.restore();
}

export function mockForbidden({
  method = 'GET',
  path,
  url,
  body = ''
}) {
  mockApi({
    method,
    path,
    body,
    url,
    status: 403,
  });
}

export function mockClient(client) {
  client.service = createSDK({});
}

export function ringOut(mockResponse = {}) {
  mockApi({
    isOnce: false,
    method: 'POST',
    url: `${mockServer}/restapi/v1.0/account/~/extension/~/ring-out`,
    body: {
      ...ringOutBody,
      ...mockResponse,
    }
  });
}

export function ringOutUpdate(mockResponse = {}) {
  mockApi({
    isOnce: false,
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/ring-out/`,
    body: {
      ...ringOutBody,
      ...mockResponse,
    }
  });
}
export function meeting(mockResponse = {}, meetingType = 'NoneRecurring') {
  mockApi({
    method: 'POST',
    isOnce: false,
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/meeting/`,
    body: {
      ...meetingBody[meetingType],
      ...mockResponse,
    }
  });
}
export function serviceInfo(mockResponse = {}) {
  mockApi({
    method: 'GET',
    url: `begin:${mockServer}/restapi/v1.0/account/~/extension/~/service-info/`,
    body: {
      ...serviceInfoBody,
      ...mockResponse,
    }
  });
}

export function mockForLogin({
  mockAuthzProfile = true,
  mockExtensionInfo = true,
  mockForwardingNumber = true,
  mockMessageSync = true,
  mockConferencing = true,
  mockActiveCalls = true
} = {}) {
  authentication();
  logout();
  tokenRefresh();
  presence('~');
  dialingPlan();
  if (mockExtensionInfo) {
    extensionInfo();
  }
  accountInfo();
  apiInfo();
  if (mockAuthzProfile) {
    authzProfile();
  }
  device();
  extensionList();
  accountPhoneNumber();
  blockedNumber();
  if (mockForwardingNumber) {
    forwardingNumber();
  }
  if (mockMessageSync) {
    messageSync();
  }
  phoneNumber();
  subscription();
  callLog();
  addressBook();
  if (mockConferencing) {
    conferencing();
  }
  if (mockActiveCalls) {
    activeCalls();
  }
}

<|endoftext|>


<commit_before>"use strict";

var webpack = require('webpack'),
    config = require('./webpack.common.config.js'),
    reversePath = __dirname + '/assets/js/shim/reverse.js';

config.output.filename = '[name]-[chunkhash].js';

// Allows require-ing the static file created by django-js-reverse
config.resolve.alias.reverse = reversePath;

config.devtool = 'source-map';

config.module.loaders.push({
    include: reversePath,
    loader: 'imports?this=>window!exports?Urls'
});

config.plugins.concat([
    new webpack.optimize.UglifyJsPlugin({
        mangle: {
            except: ['Urls', 'otm', 'google']
        }
    }),
    new webpack.optimize.OccurrenceOrderPlugin()
]);

module.exports = config;
<commit_msg>Explicitly set publicPath for production webpack configuration<commit_after>"use strict";

var webpack = require('webpack'),
    config = require('./webpack.common.config.js'),
    reversePath = __dirname + '/assets/js/shim/reverse.js';

config.output.filename = '[name]-[chunkhash].js';

// Allows require-ing the static file created by django-js-reverse
config.resolve.alias.reverse = reversePath;

config.devtool = 'source-map';

config.module.loaders.push({
    include: reversePath,
    loader: 'imports?this=>window!exports?Urls'
});

config.plugins.concat([
    new webpack.optimize.UglifyJsPlugin({
        mangle: {
            except: ['Urls', 'otm', 'google']
        }
    }),
    new webpack.optimize.OccurrenceOrderPlugin()
]);

config.output.publicPath = '/static/';

module.exports = config;
<|endoftext|>