<commit_before>/*
  react学习(一)
  个人理解,React组件分为两部分,即编写组件和使用组件
  编写组件
  var TestPlugin(组件名,首字母需要大写)=React.createClass({
    render:function(){
      return (

                Hello World!

      );//一些html标签
    }
  });
  传入一个对象,属性render返回组件的UI界面组成(html部分)

  使用组件
  ReactDOM.render(<TestPlugin />,document.getElementById("id"));
  第一个参数为编写的组件,第二个为组件要放在页面上的位置

  jsx遇到(,会解析HTML
     遇到{,会解析成JavaScript
*/
  var TestPlugin=React.createClass({
    render:function(){
      return (

                Hello World!

      );
    }
  });
  ReactDOM.render(<TestPlugin />,document.getElementById("container"));

/*
  react学习(二)
  组件的PropTypes属性
  编写组件时保证组件被正确使用变得非常有用,React的PropTypes属性可以对组件的属性值进行限定
  propTypes的常用值
  React.PropTypes.array|React.PropTypes.array.isRequired
  React.PropTypes.bool|React.PropTypes.bool.isRequired
  React.PropTypes.func|React.PropTypes.func.isRequired
  React.PropTypes.number|React.PropTypes.number.isRequired
  React.PropTypes.object|React.PropTypes.object.isRequired
  React.PropTypes.string|React.PropTypes.string.isRequired
  this.props代表组件的属性
*/
  var MyTitle=React.createClass({
    propTypes:{//此处propTypes为小写小写小写!!!
      title:React.PropTypes.string.isRequired,
    },
    render:function(){
      return (

Hello,{this.props.title}!

      );
    }
  });
  ReactDOM.render(<MyTitle title="NBA" />,document.body);
/*
  react学习(三)
  getDefaultProps来设置组件属性的默认值
*/
  var SearchPlugin=React.createClass({
    getDefaultProps:function(){
      return {
        value:"iphone 7"
      };
    },
    render:function(){
      return (

            <input type="text" value={this.props.value} />
            <button>搜索</button>

        );
    }
  });
  ReactDOM.render(<SearchPlugin />,document.getElementById("container"));
/*
  react学习(四)
  获取真实的DOM节点
  组件不是真实的DOM节点，而是存在于内存之中的一种数据结构，叫做虚拟DOM(virtual DOM).
  只有把它插入文档以后才会变成真实的DOM.所有的DOM变得都是先在虚拟DOM上发生,然后通过DOM diff算法反应到真实的DOM上
  但是若果需要获取真实的DOM节点,需要用到ref属性.
  有关于props和state的关系,可以看看这篇blog:
  http://blog.csdn.net/code_for_free/article/details/50762171

  getInitialState用于定义初始状态(是一个对象),可以通过this.state获取这个对象,this.setState方法用于修改状态值
  每次修改后自动调用this.render方法,再次渲染组件
  this.props和this.state都用于描述组件的特性,较为粗浅的区分方法是this.props表示那些一旦定义就不再改变的特性
  this.state是会随着用户互动而产生变化的特性
*/
  var SearchInput=React.createClass({
    getInitialState:function(){
      return {
        val:"iphone 7"
      };
    },
    handleFocus:function(){
      var inputnode=ReactDOM.findDOMNode(this.refs.sin);//网上说this.refs.sin就可以取到DOM节点，我试了不行，后来发现可能是版本的原因
      inputnode.style.borderColor="#2E8B57";
      this.setState({
        val:""
      });
    },
    handleBlur:function(){
      var inputnode=ReactDOM.findDOMNode(this.refs.sin);
      inputnode.style.borderColor="#DCDCDC";
      this.setState({
        val:"iphone 7"
      });
    },
    render:function(){
      return (

            <input type="text" ref="sin" value={this.state.val} onFocus={this.handleFocus} onBlur={this.handleBlur} />
            <button>搜索</button>

        );
    }
  });
  ReactDOM.render(<SearchInput />,document.getElementById("container"));
/*
  react学习(五)
  React组件之表单元素的组件
  约束性组件和非约束性组件的区分(使用value之分)
  非约束性组件:其value值由原生的DOM管理.用户输入A -> 显示A
  约束性组件:其value值由React管理.用户输入A -> 触发onChange事件 -> 事件处理函数中设置state.name=A -> 渲染标签并显示A

  不设置value(或者设置value=null)的组件是非约束性组件,此时如果想设置默认值可以使用defaultValue="sth"实现
  类型为radio,checkbox的<input />可以使用defaultChecked,<textarea />,<select />可以使用defaultValue.

  onChange事件中通过event.target.value来读取用户输入的值
*/
  var LimitPlugin=React.createClass({
    getInitialState:function(){
      return {
        value:"Hello World!"
      };
    },
    handleChange:function(event){
      this.setState({
        value:event.target.value
      });
      //如果把上面一段代码注释掉,不做任何处理,则组件为不可编辑状态
    },
    render:function(){
      return (

          <input type="text" value={this.state.value} onChange={this.handleChange} />

      );
    }
  });
  ReactDOM.render(<LimitPlugin />,document.getElementById("container"));

  var UnLimitPlugin=React.createClass({
    render:function(){
      return (

          <input type="text" defaultValue="Hello NBA!" />

      );
    }
  });
  ReactDOM.render(<UnLimitPlugin />,document.getElementById("container"));
/*
  react学习(六)
  css样式
  在React中,style行内样式不再是一个简单的字符串.它是一个{}的对象,这个对象里边的key是样式名称的驼峰命名显示,
  而value则是你想要的样式值(通常是字符串).
  1.使用{{}}来添加css样式
  var CssPlugin=React.createClass({
    render:function(){
      return (

Hello World!

      );
    }
  });
  2.使用变量单独定义
  var divStyle={color:"red"};
  var CssPlugin=React.createClass({
    render:function(){
      return (

Hello World!

      );
    }
  });
*/
/*
  react学习(七)
  组件的生命周期
  React组件的生命周期分为三个状态:
  Mount,英文有安装,嵌入,准备成立的意思
  Update,这个大家都知道,更新
  Unmount,英文意思就是卸载
  然后React为每个状态都提供了两种处理函数:will,在进入状态之前调用和did,在进入状态之后调用
  三种状态共计五个函数:
  componentWillMount(),componentDidMount(),componentWillUnmount(),
  componentWillUpdate(object nextProps,object nextState),componentDidUpdate(object prevProps,object prevState)
  组件第一次被实例化经历以下几个阶段:
  getDefaultProps->getInitialState->componentWillMount->render->componentDidMount
  以后组件的state变化时:
  shouldComponentUpdate(object nextProps,object nextState)(组件判断是否重新渲染时调用,如果没有变化则不会重新渲染)->
  componentWillUpdate->render->componentDidUpdate
  以后组件的props变化时:
  componentWillReceiveProps(object nextProps)->shouldComponentUpdate->componentWillUpdate->render->componentDidUpdate
*/
  var CounterPlugin=React.createClass({
    propTypes:{
      title:React.PropTypes.string
    },
    getDefaultProps:function(){
      console.log("getDefaultProps...");
      return {
        title:"A Counter",
        step:1
      };
    },
    getInitialState:function(){
      console.log("getInitialState...");
      return {
        num:0
      };
    },
    handleClick:function(value){
      var count=this.state.num+value;
      this.setState({
        num:count
      });
    },
    componentWillMount:function(){
      console.log("componentWillMount...");
    },
    render:function(){
      console.log("render...");
      var step=this.props.step;
      return (

{this.props.title}

{this.state.num}

            <input type="button" value="+" onClick={this.handleClick.bind(this,step)} />
            <input type="button" value="-" onClick={this.handleClick.bind(this,-step)} />

        );
    },
    componentDidMount:function(){
      console.log("componentDidMount...");
    }
  });
  ReactDOM.render(<CounterPlugin />,document.getElementById("container"));
/*
  上面一段代码加载之后,在console控制台可以看到以此打印:
  getDefaultProps...
  getInitialState...
  componentWillMount...
  render...
  componentDidMount...
*/
<commit_msg>Update exam.js<commit_after>/*
  react学习(一)
  个人理解,开发React组件分为两部分,即编写组件和使用组件
  编写组件
  var TestPlugin(组件名,首字母需要大写)=React.createClass({
    render:function(){
      return (

                Hello World!

      );//一些html标签
    }
  });
  传入一个对象,属性render返回组件的UI界面组成(html部分)

  使用组件
  ReactDOM.render(<TestPlugin />,document.getElementById("id"));
  第一个参数为编写的组件,第二个为组件要放在页面上的位置

  jsx遇到(,会解析HTML
     遇到{,会解析成JavaScript
*/
  var TestPlugin=React.createClass({
    render:function(){
      return (

                Hello World!

      );
    }
  });
  ReactDOM.render(<TestPlugin />,document.getElementById("container"));

/*
  react学习(二)
  组件的PropTypes属性
  编写组件时保证组件被正确使用变得非常有用,React的PropTypes属性可以对组件的属性值进行限定
  propTypes的常用值
  React.PropTypes.array|React.PropTypes.array.isRequired
  React.PropTypes.bool|React.PropTypes.bool.isRequired
  React.PropTypes.func|React.PropTypes.func.isRequired
  React.PropTypes.number|React.PropTypes.number.isRequired
  React.PropTypes.object|React.PropTypes.object.isRequired
  React.PropTypes.string|React.PropTypes.string.isRequired
  this.props代表组件的属性
*/
  var MyTitle=React.createClass({
    propTypes:{//此处propTypes为小写小写小写!!!
      title:React.PropTypes.string.isRequired,
    },
    render:function(){
      return (

Hello,{this.props.title}!

      );
    }
  });
  ReactDOM.render(<MyTitle title="NBA" />,document.body);
/*
  react学习(三)
  getDefaultProps来设置组件属性的默认值
*/
  var SearchPlugin=React.createClass({
    getDefaultProps:function(){
      return {
        value:"iphone 7"
      };
    },
    render:function(){
      return (

            <input type="text" value={this.props.value} />
            <button>搜索</button>

        );
    }
  });
  ReactDOM.render(<SearchPlugin />,document.getElementById("container"));
/*
  react学习(四)
  获取真实的DOM节点
  组件不是真实的DOM节点，而是存在于内存之中的一种数据结构，叫做虚拟DOM(virtual DOM).
  只有把它插入文档以后才会变成真实的DOM.所有的DOM变得都是先在虚拟DOM上发生,然后通过DOM diff算法反应到真实的DOM上
  但是若果需要获取真实的DOM节点,需要用到ref属性.
  有关于props和state的关系,可以看看这篇blog:
  http://blog.csdn.net/code_for_free/article/details/50762171

  getInitialState用于定义初始状态(是一个对象),可以通过this.state获取这个对象,this.setState方法用于修改状态值
  每次修改后自动调用this.render方法,再次渲染组件
  this.props和this.state都用于描述组件的特性,较为粗浅的区分方法是this.props表示那些一旦定义就不再改变的特性
  this.state是会随着用户互动而产生变化的特性
*/
  var SearchInput=React.createClass({
    getInitialState:function(){
      return {
        val:"iphone 7"
      };
    },
    handleFocus:function(){
      var inputnode=ReactDOM.findDOMNode(this.refs.sin);//网上说this.refs.sin就可以取到DOM节点，我试了不行，后来发现可能是版本的原因
      inputnode.style.borderColor="#2E8B57";
      this.setState({
        val:""
      });
    },
    handleBlur:function(){
      var inputnode=ReactDOM.findDOMNode(this.refs.sin);
      inputnode.style.borderColor="#DCDCDC";
      this.setState({
        val:"iphone 7"
      });
    },
    render:function(){
      return (

            <input type="text" ref="sin" value={this.state.val} onFocus={this.handleFocus} onBlur={this.handleBlur} />
            <button>搜索</button>

        );
    }
  });
  ReactDOM.render(<SearchInput />,document.getElementById("container"));
/*
  react学习(五)
  React组件之表单元素的组件
  约束性组件和非约束性组件的区分(使用value之分)
  非约束性组件:其value值由原生的DOM管理.用户输入A -> 显示A
  约束性组件:其value值由React管理.用户输入A -> 触发onChange事件 -> 事件处理函数中设置state.name=A -> 渲染标签并显示A

  不设置value(或者设置value=null)的组件是非约束性组件,此时如果想设置默认值可以使用defaultValue="sth"实现
  类型为radio,checkbox的<input />可以使用defaultChecked,<textarea />,<select />可以使用defaultValue.

  onChange事件中通过event.target.value来读取用户输入的值
*/
  var LimitPlugin=React.createClass({
    getInitialState:function(){
      return {
        value:"Hello World!"
      };
    },
    handleChange:function(event){
      this.setState({
        value:event.target.value
      });
      //如果把上面一段代码注释掉,不做任何处理,则组件为不可编辑状态
    },
    render:function(){
      return (

          <input type="text" value={this.state.value} onChange={this.handleChange} />

      );
    }
  });
  ReactDOM.render(<LimitPlugin />,document.getElementById("container"));

  var UnLimitPlugin=React.createClass({
    render:function(){
      return (

          <input type="text" defaultValue="Hello NBA!" />

      );
    }
  });
  ReactDOM.render(<UnLimitPlugin />,document.getElementById("container"));
/*
  react学习(六)
  css样式
  在React中,style行内样式不再是一个简单的字符串.它是一个{}的对象,这个对象里边的key是样式名称的驼峰命名显示,
  而value则是你想要的样式值(通常是字符串).
  1.使用{{}}来添加css样式
  var CssPlugin=React.createClass({
    render:function(){
      return (

Hello World!

      );
    }
  });
  2.使用变量单独定义
  var divStyle={color:"red"};
  var CssPlugin=React.createClass({
    render:function(){
      return (

Hello World!

      );
    }
  });
*/
/*
  react学习(七)
  组件的生命周期
  React组件的生命周期分为三个状态:
  Mount,英文有安装,嵌入,准备成立的意思
  Update,这个大家都知道,更新
  Unmount,英文意思就是卸载
  然后React为每个状态都提供了两种处理函数:will,在进入状态之前调用和did,在进入状态之后调用
  三种状态共计五个函数:
  componentWillMount(),componentDidMount(),componentWillUnmount(),
  componentWillUpdate(object nextProps,object nextState),componentDidUpdate(object prevProps,object prevState)
  组件第一次被实例化经历以下几个阶段:
  getDefaultProps->getInitialState->componentWillMount->render->componentDidMount
  以后组件的state变化时:
  shouldComponentUpdate(object nextProps,object nextState)(组件判断是否重新渲染时调用,如果没有变化则不会重新渲染)->
  componentWillUpdate->render->componentDidUpdate
  以后组件的props变化时:
  componentWillReceiveProps(object nextProps)->shouldComponentUpdate->componentWillUpdate->render->componentDidUpdate
*/
  var CounterPlugin=React.createClass({
    propTypes:{
      title:React.PropTypes.string
    },
    getDefaultProps:function(){
      console.log("getDefaultProps...");
      return {
        title:"A Counter",
        step:1
      };
    },
    getInitialState:function(){
      console.log("getInitialState...");
      return {
        num:0
      };
    },
    handleClick:function(value){
      var count=this.state.num+value;
      this.setState({
        num:count
      });
    },
    componentWillMount:function(){
      console.log("componentWillMount...");
    },
    render:function(){
      console.log("render...");
      var step=this.props.step;
      return (

{this.props.title}

{this.state.num}

            <input type="button" value="+" onClick={this.handleClick.bind(this,step)} />
            <input type="button" value="-" onClick={this.handleClick.bind(this,-step)} />

        );
    },
    componentDidMount:function(){
      console.log("componentDidMount...");
    },
    shouldComponentUpdate:function(nextProps,nextState){
      console.log("shouldComponentUpdate...");
      if(this.state.num===nextState.num){
        return false;
      }else{
        return true;
      }
    },
    componentWillUpdate:function(){
        console.log("componentWillUpdate...");
    },
    componentDidUpdate:function(){
        console.log("componentDidUpdate...");
    }
  });
  ReactDOM.render(<CounterPlugin />,document.getElementById("container"));
/*
  上面一段代码加载之后,在console控制台可以看到以此打印:
  getDefaultProps...
  getInitialState...
  componentWillMount...
  render...
  componentDidMount...
  然后每次单击 +/- 按钮时可以看到console控制台会依次打印出:
  shouldComponentUpdate...
  componentWillUpdate...
  render...
  componentDidUpdate...

  componentWillMount函数调用时,this.refs对象为空对象,如果在此函数中调用this.setState,则会更新state对象,相当于会覆盖getInitialState
  函数返回的对象信息,虽然这样做没有什么意义.

  componentDidMount是非常常用的生命周期方法,仅当组件被挂载后调用一次,这意味着可以在这个函数中进行一些DOM操作等,
  比如希望组件中的一个textbox可以再挂载后自动获取焦点.

  componentWillReceiveProps在将要接受新的props时被调用,不是说props是不可变状态吗?
  情况通常是这样的,当一个父组件包含了一个子组件,子组件的一个props的值是父组件的states的值,
  那么当父组件可变状态改变时,子组件的props也更新了,于是调用了这个函数.
  这个生命周期函数componentWillReceiveProps提供了更新states的机会,可以调用this.setState,
  也是唯一可以在组件更新周期中调用this.setState的函数.

  shouldComponentUpdate是在更新前根据该函数的返回值决定是否进行这次更新.
  shouldComponentUpdate (nextProps, nextState) {
    // 比较props或者state，返回true则更新照常，返回false则取消更新，且不会调用下面的两个生命周期函数
  }
  注意:绝对不要在componentWillUpdate和componentDidUpdate中调用this.setState方法,否则将导致无限循环调用.

  componentWillUnmount会在组件即将从挂载点移去时调用.

  **以上这段文字来自于 —— ／leozdgao（简书作者）原文链接：http://www.jianshu.com/p/788a82dac136**
*/
<|endoftext|>


<commit_before>'use strict';
// declare and import packages
let nodestalkerAsync = require('nodestalker-async');
let chai = require('chai');
let co = require('co');
let uuid = require('uuid');
let beanworker = require('fivebeans');
let winston = require('winston');
let expect = chai.expect;
let config = require('./../config');
let Seed = require('./../lib/seed');
let ExchangeRateHandler = require('./../lib/exchange_rate_handler');

// Unit test on the Seed
describe('Seed', function () {
	let client;
// before hook
	beforeEach(function (done) {
// declare the nodestalk client
		client = new nodestalkerAsync.Client(config.beanstalkd_host, config.beanstalkd_port);
		client.useAsync(config.beanstalkd_tube);
		done();
	});
// after hook
	afterEach(function () {
		client.disconnect();
	});
// unit test the function fail_put in Seed after the excahge rate attempt is failed and the fail count is less than 3 times
	describe('#fail_put', function () {
		describe('#fail_count < FAIL_ATTEMPT', function () {
// put the seed to the beanstalkd server
			let seed = new Seed(config, 'HKD', 'USD', 2, 1);
			it('fail_count is increased by one and reput the seed to the beanstalk server which becomes ready after 3s', function (done) {
				co(function*() {
// get the job id
					let job_id_seed = yield seed.fail_put();
// get the job stats
					let job_peek_stats = yield client.statsJobAsync(job_id_seed);
// peek the job from the beanstalk server
					let job_peek = yield client.peekAsync(job_id_seed);
// delete the job
					let delete_job = yield client.deleteJobAsync(job_id_seed);
// check the job delay with 3s
					expect(job_peek_stats[0].delay).to.equal(3);
// check the seed data is equal to the payload
					expect(seed.toJson()).to.equal(job_peek[0].data);
// check the job is deleted
					expect(delete_job[0][0]).to.equal('DELETED');
					done();
				}).catch(function (err) {
					winston.error(err);
				});
			});
		});
// Unit test for the function fail_put in Seed after the excahge rate attempt is failed and the fail count is equal to 3 times
		describe('#fail_count == FAIL_ATTEMPT', function () {
// put the seed to the beanstalkd server
			let seed = new Seed(config, 'HKD', 'USD', 9, 2);
			it('The job is failed and no further seed reput ', function (done) {
				co(function*() {
// get the job id
					let job_id_seed = yield seed.fail_put();
// expect the results is equal to 'FINISHED ALL ATTEMPTS WITH FAIL' if the fail attempt is 3 times
					expect(job_id_seed).to.equal('FINISHED ALL ATTEMPTS WITH FAIL AND THE JOB IS BURIED');
					done();
				}).catch(function (err) {
					winston.error(err);
					done();
				});
			});
		});
	});
// Unit test for the function success_put in Seed after the excahge rate attempt is success
	describe('#success_put', function () {
// Unit test for the function success_put in Seed after the excahge rate attempt is success and the success count is less than 10 times
		describe('#success_count < SUCCESS_ATTEMPT', function () {
			let seed = new Seed(config, 'HKD', 'USD', 2, 1);
			it('success_count is increased by one and reput the seed to the beanstalk server which becomes ready after 60s', function (done) {
				co(function*() {
// get the job id
					let job_id_seed = yield seed.success_put();
// get the job stats
					let job_peek_stats = yield client.statsJobAsync(job_id_seed);
// peek the job from the beanstalkd server
					let job_peek = yield client.peekAsync(job_id_seed);
// delete the job after test
					let delete_job = yield client.deleteJobAsync(job_id_seed);
// check the job with delay 60s
					expect(job_peek_stats[0].delay).to.equal(60);
// check the job data is the same as the seed
					expect(seed.toJson()).to.equal(job_peek[0].data);
// check the job is deleted
					expect(delete_job[0][0]).to.equal('DELETED');
					done();
				}).catch(function (err) {
					console.log(err);
				});
			});
		});
// Unit test for the function success_put in Seed after the excahge rate attempt is success and the success count is equal to 10 times
		describe('#success_count == SUCCESS_ATTEMPT', function () {
// put the seed into the beanstalkd server
			let seed = new Seed(config, 'HKD', 'USD', 9, 1);
			it('The job is finished and no further seed reput ', function (done) {
				co(function*() {
// get the job id
					let job_id_seed = yield seed.success_put();
// check the job is finished after 10 success attempts
					expect(job_id_seed).to.equal('FINISHED ALL ATTEMPTS WITH SUCCESS');
					done();
				}).catch(function (err) {
					winston.error(err);
					expect(err).to.equal('SUCCESS PUT ERROR');
					done();
				});
			});
		});
	});
// Unit test for the function put in Seed
	describe('#put', function () {
		it('should return the same job number and json string', function (done) {
			let seed = new Seed(config, 'HKD', 'USD', 0, 0);
			co(function*() {
// get the job id
				let job_from_seed = yield seed.put(0);
				let job_id_seed = parseInt(job_from_seed, 10);
// peek the job
				let job_peek = yield client.peekAsync(job_id_seed);
				let job_id_peek = parseInt(job_peek[0].id, 10);
// delete the job
				let delete_job = yield client.deleteJobAsync(job_id_peek);
// check the job id
				expect(parseInt(job_from_seed, 10)).to.equal(job_id_peek);
// expect the seed is equal to the job data
				expect(seed.toJson()).to.equal(job_peek[0].data);
// deleted the job
				expect(delete_job[0][0]).to.equal('DELETED');
				done();
			}).catch(function (err) {
				winston.error(err);
			});
		});
	});
});

// Unit test for Worker Customer
describe('Consumer Worker', function () {
// set longer timeout
	this.timeout(800000);
// define the options for the bean worker
	let options =
		{
			id: uuid.v4(),
			host: config.beanstalkd_host,
			port: config.beanstalkd_port,
			handlers:
				{
					exchange_rate: new ExchangeRateHandler(config)
				},
			ignoreDefault: true
		};
	let worker;
	let client;
	let handler;
// before hook
	before(function (done) {
// decalre the bean worker
		worker = new beanworker.worker(options);
		worker.on('started', done);
		worker.start([config.beanstalkd_tube]);
// declare the nodestalker client for checking
		client = new nodestalkerAsync.Client(config.beanstalkd_host, config.beanstalkd_port);
		client.useAsync(config.beanstalkd_tube);
		// connect the event emitter to the worker handler
		handler = worker.handlers.exchange_rate;
	});
// after hook
	after(function () {
		worker.stop();
		client.disconnect();
	});

// Unit test for the work function in exchange_rate_handler to handle 10 times exchange rate attempts with success
	describe('#work_success', function () {
		let seed_put = -1;
// reset the count to zero
		let success_count = 0;
		it('save 10 successful rate results to mongodb then that currency converstaion job is done', function (done) {
// put the seed to the beanstalkd server
			let seed = new Seed(config, 'EUR', 'USD', 0, 1);
// listen to the beanwork handler
			handler.on('exchange_rate_handler', verifyResult);
			co(function*() {
// get the job id
				seed_put = yield seed.put(0);
			}).catch(function (err) {
				winston.error(err);
			});
// Callback function of the worker handler
// @param {Object} item - data from eventEmitter in function exchange_rate_handler.work
			function verifyResult(item)	{
// get the job_id
				seed_put = parseInt(seed_put, 10);
				let job_id = parseInt(item.job_id, 10);
// consider only job_id is matched because there is other job in the queue
				if (seed_put === job_id) {
// set the seed_put for next job_id matched
					seed_put = item.put_seed;
					// verify the object key callback from mongodb exists
					expect(item.mongo_save._id).to.exist;
					// verify the mongodb data
					expect(item.mongo_save.rate).to.equal(item.exchange_rate);
					expect(item.mongo_save.from).to.equal(item.payload.from);
					expect(item.mongo_save.to).to.equal(item.payload.to);
					expect(item.mongo_save.created_at).to.exist;
// finish the job if succeed 10 times
					if (success_count === 9) {
// remove the listen to the handler
						handler.removeListener('exchange_rate_handler', verifyResult);
// check the success_count is equal to 9
						expect(success_count).to.equal(9);
						done();
					} else {
// the succes_count is increased by one
						success_count ++;
					}
				}
			}
		});
	});
// Unit test for the work function in exchange_rate_handler to handle 3 times exchange rate attempts failed
	describe('#work_fail', function () {
		let seed_put = -1;
		let fail_count = 0;
		it('If any problem during the get rate attempt, retry it delay with 3s and bury the after 3 times in total', function (done) {
			co(function*() {
				// declare a new seed with curreny not existed
				let seed = new Seed(config, 'HKDD', 'USD', 3, 0);
				// listen to the beanworker handler
				handler.on('exchange_rate_handler', verifyError);
// get the job_id
				seed_put = yield seed.put(0);
			}).catch(function (err) {
				winston.error(err);
			});
			function verifyError(item) {
				seed_put = parseInt(seed_put, 10);
				let job_id = parseInt(item.job_id, 10);
				if (seed_put === job_id) {
// check the item.put_fail is number or not
					if (isInteger(item.put_fail)) {
// set the seed_put for the next callback
						seed_put = item.put_fail;
// fail_count is increased by one
						fail_count ++;
					} else if (fail_count === 2) {
// remove the listener if the job tried 3 times with fail
						handler.removeListener('exchange_rate_handler', verifyError);
// check the fail_count is equal to 2
						expect(fail_count).to.equal(2);
// check the put_fail returned the correct string after 3 fail tries
						expect(item.put_fail).to.equal('FINISHED ALL ATTEMPTS WITH FAIL AND THE JOB IS BURIED');
//check the job is BURIED
						done();
					} else {
// check the put_fail returned the correct string if the fail count is invalid
						expect(item.put_fail).to.equal('FAIL_COUNT IS INVALID');
						done();
					}
				}
			}
			/**
			* Function to verify the input is integer or not
			* @return {Object} regex result
		*/
			function isInteger(input) {
				let regex = /\d/g;
				let check_format = regex.exec(input);
				return check_format;
			}
		});
	});
});
<commit_msg>#FIX Update the format in test.js<commit_after>'use strict';
// declare and import packages
let nodestalkerAsync = require('nodestalker-async');
let chai = require('chai');
let co = require('co');
let uuid = require('uuid');
let beanworker = require('fivebeans');
let winston = require('winston');
let expect = chai.expect;
let config = require('./../config');
let Seed = require('./../lib/seed');
let ExchangeRateHandler = require('./../lib/exchange_rate_handler');

// Unit test on the Seed
describe('Seed', function () {
	let client;
// before hook
	beforeEach(function (done) {
// declare the nodestalk client
		client = new nodestalkerAsync.Client(config.beanstalkd_host, config.beanstalkd_port);
		client.useAsync(config.beanstalkd_tube);
		done();
	});
// after hook
	afterEach(function () {
		client.disconnect();
	});
// unit test the function fail_put in Seed after the excahge rate attempt is failed and the fail count is less than 3 times
	describe('#fail_put', function () {
		describe('#fail_count < FAIL_ATTEMPT', function () {
// put the seed to the beanstalkd server
			let seed = new Seed(config, 'HKD', 'USD', 2, 1);
			it('fail_count is increased by one and reput the seed to the beanstalk server which becomes ready after 3s', function (done) {
				co(function*() {
// get the job id
					let job_id_seed = yield seed.fail_put();
// get the job stats
					let job_peek_stats = yield client.statsJobAsync(job_id_seed);
// peek the job from the beanstalk server
					let job_peek = yield client.peekAsync(job_id_seed);
// delete the job
					let delete_job = yield client.deleteJobAsync(job_id_seed);
// check the job delay with 3s
					expect(job_peek_stats[0].delay).to.equal(3);
// check the seed data is equal to the payload
					expect(seed.toJson()).to.equal(job_peek[0].data);
// check the job is deleted
					expect(delete_job[0][0]).to.equal('DELETED');
					done();
				}).catch(function (err) {
					winston.error(err);
				});
			});
		});
// Unit test for the function fail_put in Seed after the excahge rate attempt is failed and the fail count is equal to 3 times
		describe('#fail_count == FAIL_ATTEMPT', function () {
// put the seed to the beanstalkd server
			let seed = new Seed(config, 'HKD', 'USD', 9, 2);
			it('The job is failed and no further seed reput ', function (done) {
				co(function*() {
// get the job id
					let job_id_seed = yield seed.fail_put();
// expect the results is equal to 'FINISHED ALL ATTEMPTS WITH FAIL' if the fail attempt is 3 times
					expect(job_id_seed).to.equal('FINISHED ALL ATTEMPTS WITH FAIL AND THE JOB IS BURIED');
					done();
				}).catch(function (err) {
					winston.error(err);
					done();
				});
			});
		});
	});
// Unit test for the function success_put in Seed after the excahge rate attempt is success
	describe('#success_put', function () {
// Unit test for the function success_put in Seed after the excahge rate attempt is success and the success count is less than 10 times
		describe('#success_count < SUCCESS_ATTEMPT', function () {
			let seed = new Seed(config, 'HKD', 'USD', 2, 1);
			it('success_count is increased by one and reput the seed to the beanstalk server which becomes ready after 60s', function (done) {
				co(function*() {
// get the job id
					let job_id_seed = yield seed.success_put();
// get the job stats
					let job_peek_stats = yield client.statsJobAsync(job_id_seed);
// peek the job from the beanstalkd server
					let job_peek = yield client.peekAsync(job_id_seed);
// delete the job after test
					let delete_job = yield client.deleteJobAsync(job_id_seed);
// check the job with delay 60s
					expect(job_peek_stats[0].delay).to.equal(60);
// check the job data is the same as the seed
					expect(seed.toJson()).to.equal(job_peek[0].data);
// check the job is deleted
					expect(delete_job[0][0]).to.equal('DELETED');
					done();
				}).catch(function (err) {
					console.log(err);
				});
			});
		});
// Unit test for the function success_put in Seed after the excahge rate attempt is success and the success count is equal to 10 times
		describe('#success_count == SUCCESS_ATTEMPT', function () {
// put the seed into the beanstalkd server
			let seed = new Seed(config, 'HKD', 'USD', 9, 1);
			it('The job is finished and no further seed reput ', function (done) {
				co(function*() {
// get the job id
					let job_id_seed = yield seed.success_put();
// check the job is finished after 10 success attempts
					expect(job_id_seed).to.equal('FINISHED ALL ATTEMPTS WITH SUCCESS');
					done();
				}).catch(function (err) {
					winston.error(err);
					expect(err).to.equal('SUCCESS PUT ERROR');
					done();
				});
			});
		});
	});
// Unit test for the function put in Seed
	describe('#put', function () {
		it('should return the same job number and json string', function (done) {
			let seed = new Seed(config, 'HKD', 'USD', 0, 0);
			co(function*() {
// get the job id
				let job_from_seed = yield seed.put(0);
				let job_id_seed = parseInt(job_from_seed, 10);
// peek the job
				let job_peek = yield client.peekAsync(job_id_seed);
				let job_id_peek = parseInt(job_peek[0].id, 10);
// delete the job
				let delete_job = yield client.deleteJobAsync(job_id_peek);
// check the job id
				expect(parseInt(job_from_seed, 10)).to.equal(job_id_peek);
// expect the seed is equal to the job data
				expect(seed.toJson()).to.equal(job_peek[0].data);
// deleted the job
				expect(delete_job[0][0]).to.equal('DELETED');
				done();
			}).catch(function (err) {
				winston.error(err);
			});
		});
	});
});

// Unit test for Worker Customer
describe('Consumer Worker', function () {
// set longer timeout
	this.timeout(800000);
// define the options for the bean worker
	let options =
		{
			id: uuid.v4(),
			host: config.beanstalkd_host,
			port: config.beanstalkd_port,
			handlers:
				{
					exchange_rate: new ExchangeRateHandler(config)
				},
			ignoreDefault: true
		};
	let worker;
	let client;
	let handler;
// before hook
	before(function (done) {
// decalre the bean worker
		worker = new beanworker.worker(options);
		worker.on('started', done);
		worker.start([config.beanstalkd_tube]);
// declare the nodestalker client for checking
		client = new nodestalkerAsync.Client(config.beanstalkd_host, config.beanstalkd_port);
		client.useAsync(config.beanstalkd_tube);
		// connect the event emitter to the worker handler
		handler = worker.handlers.exchange_rate;
	});
// after hook
	after(function () {
		worker.stop();
		client.disconnect();
	});

// Unit test for the work function in exchange_rate_handler to handle 10 times exchange rate attempts with success
	describe('#work_success', function () {
		let seed_put = -1;
// reset the count to zero
		let success_count = 0;
		it('save 10 successful rate results to mongodb then that currency converstaion job is done', function (done) {
// put the seed to the beanstalkd server
			let seed = new Seed(config, 'EUR', 'USD', 0, 1);
// listen to the beanwork handler
			handler.on('exchange_rate_handler', verifyResult);
			co(function*() {
// get the job id
				seed_put = yield seed.put(0);
			}).catch(function (err) {
				winston.error(err);
			});
// Callback function of the worker handler
// @param {Object} item - data from eventEmitter in function exchange_rate_handler.work
			function verifyResult(item)	{
// get the job_id
				seed_put = parseInt(seed_put, 10);
				let job_id = parseInt(item.job_id, 10);
// consider only job_id is matched because there is other job in the queue
				if (seed_put === job_id) {
// set the seed_put for next job_id matched
					seed_put = item.put_seed;
					// verify the object key callback from mongodb exists
					expect(item.mongo_save._id).to.exist;
					// verify the mongodb data
					expect(item.mongo_save.rate).to.equal(item.exchange_rate);
					expect(item.mongo_save.from).to.equal(item.payload.from);
					expect(item.mongo_save.to).to.equal(item.payload.to);
					expect(item.mongo_save.created_at).to.exist;
// finish the job if succeed 10 times
					if (success_count === 9) {
// remove the listen to the handler
						handler.removeListener('exchange_rate_handler', verifyResult);
// check the success_count is equal to 9
						expect(success_count).to.equal(9);
						done();
					} else {
// the succes_count is increased by one
						success_count ++;
					}
				}
			}
		});
	});
// Unit test for the work function in exchange_rate_handler to handle 3 times exchange rate attempts failed
	describe('#work_fail', function () {
		let seed_put = -1;
		let fail_count = 0;
		it('If any problem during the get rate attempt, retry it delay with 3s and bury the after 3 times in total', function (done) {
			co(function*() {
				// declare a new seed with curreny not existed
				let seed = new Seed(config, 'HKDD', 'USD', 3, 0);
				// listen to the beanworker handler
				handler.on('exchange_rate_handler', verifyError);
// get the job_id
				seed_put = yield seed.put(0);
			}).catch(function (err) {
				winston.error(err);
			});
			function verifyError(item) {
				seed_put = parseInt(seed_put, 10);
				let job_id = parseInt(item.job_id, 10);
				if (seed_put === job_id) {
// check the item.put_fail is number or not
					if (isInteger(item.put_fail)) {
// set the seed_put for the next callback
						seed_put = item.put_fail;
// fail_count is increased by one
						fail_count ++;
					} else if (fail_count === 2) {
// remove the listener if the job tried 3 times with fail
						handler.removeListener('exchange_rate_handler', verifyError);
// check the fail_count is equal to 2
						expect(fail_count).to.equal(2);
// check the put_fail returned the correct string after 3 fail tries
						expect(item.put_fail).to.equal('FINISHED ALL ATTEMPTS WITH FAIL AND THE JOB IS BURIED');
// check the job is BURIED
						done();
					} else {
// check the put_fail returned the correct string if the fail count is invalid
						expect(item.put_fail).to.equal('FAIL_COUNT IS INVALID');
						done();
					}
				}
			}
			/**
			* Function to verify the input is integer or not
			* @return {Object} regex result
		*/
			function isInteger(input) {
				let regex = /\d/g;
				let check_format = regex.exec(input);
				return check_format;
			}
		});
	});
});
<|endoftext|>


<commit_before><commit_msg>Improve backbone history stub<commit_after><|endoftext|>


<commit_before>'use strict'

const WFSM = require('../src/index.js');
var assert = require('assert');

it('removeEpsilon', function() {

	var wfsm = new WFSM();
	wfsm.setE( 0, 1, 0, 0, 0.25 );
	wfsm.setE( 0, 1, wfsm.EPS, wfsm.EPS, 0.5 );
	wfsm.setE( 1, 1, wfsm.EPS, wfsm.EPS, 0.2 );
	wfsm.setE( 1, 0, 1, 1, 0.5 );

	wfsm.setI( 1, 1 );
	wfsm.setF( 1, 0.3 );
	wfsm.setF( 0, 0.25 );

	wfsm.removeEpsilon();
	assert.equal(JSON.stringify(wfsm.Q), '[[{"0":{"1":{"1":0.3125}},"1":{"0":{"0":0.25},"-1":{}}},0.4375,0],[{"0":{"1":{"1":0.625}},"1":{"-1":{}}},0.375,1]]');
});
<commit_msg>Add union.<commit_after>'use strict'

const WFSM = require('../src/index.js');
var assert = require('assert');

it('removeEpsilon', function() {

	var wfsm = new WFSM();
	wfsm.setE( 0, 1, 0, 0, 0.25 );
	wfsm.setE( 0, 1, wfsm.EPS, wfsm.EPS, 0.5 );
	wfsm.setE( 1, 1, wfsm.EPS, wfsm.EPS, 0.2 );
	wfsm.setE( 1, 0, 1, 1, 0.5 );

	wfsm.setI( 1, 1 );
	wfsm.setF( 1, 0.3 );
	wfsm.setF( 0, 0.25 );

	wfsm.removeEpsilon();
	assert.equal(JSON.stringify(wfsm.Q), '[[{"0":{"1":{"1":0.3125}},"1":{"0":{"0":0.25},"-1":{}}},0.4375,0],[{"0":{"1":{"1":0.625}},"1":{"-1":{}}},0.375,1]]');
});

it('union', function() {

	var fsm1 = new WFSM();
	fsm1.setE( 0, 1, 0 );
	fsm1.setE( 0, 2, 1 );
	fsm1.setI( 0, 0.4 );
	fsm1.setF( 1 );
	fsm1.setF( 2 );

	var fsm2 = new WFSM();
	fsm2.setE( 0, 1, 2 );
	fsm2.setI( 0, 0.6 );
	fsm2.setF( 1 );

	fsm1.union( fsm2 );

	assert.equal(JSON.stringify(fsm1.Q), '[[{"1":{"0":{"0":1}},"2":{"1":{"1":1}}},0,0],[{},1,0],[{},1,0],[{"0":{"-1":{"-1":0.4}},"4":{"-1":{"-1":0.6}}},0,1]]');

});
<|endoftext|>


<commit_before>var path = require( 'path' );
var fs = require( 'fs' );
var rimraf = require( 'rimraf' );
var child_process = require( 'child_process' );
var assert = require( 'assert' );
var glob = require( 'glob' );
var SourceMapConsumer = require( 'source-map' ).SourceMapConsumer;
var getLocation = require( './utils/getLocation.js' );
var buble = require( '../dist/buble.umd.js' );

require( 'source-map-support' ).install();
require( 'console-group' ).install();

function equal ( a, b ) {
	assert.equal( showInvisibles( a ), showInvisibles( b ) );
}

function showInvisibles ( str ) {
	return str
		.replace( /^ +/gm, spaces => repeat( '•', spaces.length ) )
		.replace( / +$/gm, spaces => repeat( '•', spaces.length ) )
		.replace( /^\t+/gm, tabs => repeat( '›   ', tabs.length ) )
		.replace( /\t+$/gm, tabs => repeat( '›   ', tabs.length ) );
}

function repeat ( str, times ) {
	var result = '';
	while ( times-- ) result += str;
	return result;
}

const subsetIndex = process.argv.indexOf( '--subset' );
const subset = ~subsetIndex ? process.argv[ subsetIndex + 1 ].split( ',' ).map( file => `${file}.js` ) : null;
const subsetFilter = subset ? file => ~subset.indexOf( file ) : () => true;

describe( 'buble', () => {
	fs.readdirSync( 'test/samples' ).filter( subsetFilter ).forEach( file => {
		if ( !/\.js$/.test( file ) ) return; // avoid vim .js.swp files
		var samples = require( './samples/' + file );

		describe( path.basename( file ), () => {
			samples.forEach( sample => {
				( sample.solo ? it.only : sample.skip ? it.skip : it )( sample.description, () => {
					if ( sample.error ) {
						assert.throws( () => {
							buble.transform( sample.input, sample.options );
						}, sample.error );
					}

					else {
						equal( buble.transform( sample.input, sample.options  ).code, sample.output );
					}
				});
			});
		});
	});

	if ( subset ) return;

	describe( 'cli', () => {
		fs.readdirSync( 'test/cli' ).forEach( dir => {
			if ( dir[0] === '.' ) return; // .DS_Store

			it( dir, done => {
				dir = path.resolve( 'test/cli', dir );
				rimraf.sync( path.resolve( dir, 'actual' ) );
				fs.mkdirSync( path.resolve( dir, 'actual' ) );

				var binFile = path.resolve(__dirname, '../bin/buble');
				var commandFile = path.resolve( dir, 'command.sh' );

				var command = fs.readFileSync( commandFile, 'utf-8' )
					.replace( 'buble', 'node "' + binFile + '"' );
				child_process.exec( command, {
					cwd: dir
				}, ( err, stdout, stderr ) => {
					if ( err ) return done( err );

					if ( stdout ) console.log( stdout );
					if ( stderr ) console.error( stderr );

					function catalogue ( subdir ) {
						subdir = path.resolve( dir, subdir );

						return glob.sync( '**/*.js?(.map)', { cwd: subdir })
							.sort()
							.map( name => {
								var contents = fs.readFileSync( path.resolve( subdir, name ), 'utf-8' ).trim();

								if ( path.extname( name ) === '.map' ) {
									contents = JSON.parse( contents );
								}

								return {
									name: name,
									contents: contents
								};
							});
					}

					var expected = catalogue( 'expected' );
					var actual = catalogue( 'actual' );

					try {
						assert.deepEqual( actual, expected );
						done();
					} catch ( err ) {
						done( err );
					}
				});
			});
		});
	});

	describe( 'errors', () => {
		it( 'reports the location of a syntax error', () => {
			var source = `var 42 = nope;`;

			try {
				buble.transform( source );
			} catch ( err ) {
				assert.equal( err.name, 'SyntaxError' );
				assert.deepEqual( err.loc, { line: 1, column: 4 });
				assert.equal( err.message, 'Unexpected token (1:4)' );
				assert.equal( err.snippet, `1 : var 42 = nope;\n        ^` );
				assert.equal( err.toString(), `SyntaxError: Unexpected token (1:4)\n1 : var 42 = nope;\n        ^` );
			}
		});

		it( 'reports the location of a compile error', () => {
			var source = `const x = 1; x++;`;

			try {
				buble.transform( source );
			} catch ( err ) {
				assert.equal( err.name, 'CompileError' );
				assert.equal( err.loc.line, 1 );
				assert.equal( err.loc.column, 13 );
				assert.equal( err.message, 'x is read-only (1:13)' );
				assert.equal( err.snippet, `1 : const x = 1; x++;\n                 ^^^` );
				assert.equal( err.toString(), `CompileError: x is read-only (1:13)\n1 : const x = 1; x++;\n                 ^^^` );
			}
		});
	});

	describe( 'target', () => {
		it( 'determines necessary transforms for a target environment', () => {
			var transforms = buble.target({ chrome: 49 });

			assert.ok( transforms.moduleImport );
			assert.ok( !transforms.arrow );
		});

		it( 'returns lowest common denominator support info', () => {
			var transforms = buble.target({ chrome: 49, node: 5 });

			assert.ok( transforms.defaultParameter );
			assert.ok( !transforms.arrow );
		});

		it( 'only applies necessary transforms', () => {
			var source = `
				const power = ( base, exponent = 2 ) => Math.pow( base, exponent );`;

			var result = buble.transform( source, {
				target: { chrome: 49, node: 5 }
			}).code;

			assert.equal( result, `
				const power = ( base, exponent ) => {
					if ( exponent === void 0 ) exponent = 2;

					return Math.pow( base, exponent );
				};` );
		});
	});

	describe( 'sourcemaps', () => {
		it( 'generates a valid sourcemap', () => {
			var map = buble.transform( '' ).map;
			assert.equal( map.version, 3 );
		});

		it( 'uses provided file and source', () => {
			var map = buble.transform( '', {
				file: 'output.js',
				source: 'input.js'
			}).map;

			assert.equal( map.file, 'output.js' );
			assert.deepEqual( map.sources, [ 'input.js' ] );
		});

		it( 'includes content by default', () => {
			var source = `let { x, y } = foo();`;
			var map = buble.transform( source ).map;

			assert.deepEqual( map.sourcesContent, [ source ] );
		});

		it( 'excludes content if requested', () => {
			var source = `let { x, y } = foo();`;
			var map = buble.transform( source, {
				includeContent: false
			}).map;

			assert.deepEqual( map.sourcesContent, [ null ] );
		});

		it( 'locates original content', () => {
			var source = `const add = ( a, b ) => a + b;`;
			var result = buble.transform( source, {
				file: 'output.js',
				source: 'input.js'
			});

			var smc = new SourceMapConsumer( result.map );

			var location = getLocation( result.code, 'add' );
			var expected = getLocation( source, 'add' );

			var actual = smc.originalPositionFor( location );

			assert.deepEqual( actual, {
				line: expected.line,
				column: expected.column,
				source: 'input.js',
				name: null
			});

			location = getLocation( result.code, 'a +' );
			expected = getLocation( source, 'a +' );

			actual = smc.originalPositionFor( location );

			assert.deepEqual( actual, {
				line: expected.line,
				column: expected.column,
				source: 'input.js',
				name: null
			});
		});

		it( 'recovers names', () => {
			var source = `
				const foo = 1;
				if ( x ) {
					const foo = 2;
				}`;

			var result = buble.transform( source, {
				file: 'output.js',
				source: 'input.js'
			});
			var smc = new SourceMapConsumer( result.map );

			var location = getLocation( result.code, 'var' );
			var actual = smc.originalPositionFor( location );

			assert.equal( actual.name, 'const' );

			location = getLocation( result.code, 'var', location.char + 1 );
			actual = smc.originalPositionFor( location );

			assert.equal( actual.name, 'const' );

			location = getLocation( result.code, 'foo$1', location.char + 1 );
			actual = smc.originalPositionFor( location );

			assert.equal( actual.name, 'foo' );
		});

		it( 'handles moved content', () => {
			var source = `
				for ( let i = 0; i < 10; i += 1 ) {
					const square = i * i;
					setTimeout( function () {
						log( square );
					}, i * 100 );
				}`;

			var result = buble.transform( source, {
				file: 'output.js',
				source: 'input.js'
			});
			var smc = new SourceMapConsumer( result.map );

			var location = getLocation( result.code, 'i < 10' );
			var expected = getLocation( source, 'i < 10' );

			var actual = smc.originalPositionFor( location );

			assert.deepEqual( actual, {
				line: expected.line,
				column: expected.column,
				source: 'input.js',
				name: null
			});

			location = getLocation( result.code, 'setTimeout' );
			expected = getLocation( source, 'setTimeout' );

			actual = smc.originalPositionFor( location );

			assert.deepEqual( actual, {
				line: expected.line,
				column: expected.column,
				source: 'input.js',
				name: null
			});
		});
	});
});
<commit_msg>get tests to pass on windows, hopefully<commit_after>var path = require( 'path' );
var fs = require( 'fs' );
var rimraf = require( 'rimraf' );
var child_process = require( 'child_process' );
var assert = require( 'assert' );
var glob = require( 'glob' );
var SourceMapConsumer = require( 'source-map' ).SourceMapConsumer;
var getLocation = require( './utils/getLocation.js' );
var buble = require( '../dist/buble.umd.js' );

require( 'source-map-support' ).install();
require( 'console-group' ).install();

function equal ( a, b ) {
	assert.equal( showInvisibles( a ), showInvisibles( b ) );
}

function showInvisibles ( str ) {
	return str
		.replace( /^ +/gm, spaces => repeat( '•', spaces.length ) )
		.replace( / +$/gm, spaces => repeat( '•', spaces.length ) )
		.replace( /^\t+/gm, tabs => repeat( '›   ', tabs.length ) )
		.replace( /\t+$/gm, tabs => repeat( '›   ', tabs.length ) );
}

function repeat ( str, times ) {
	var result = '';
	while ( times-- ) result += str;
	return result;
}

const subsetIndex = process.argv.indexOf( '--subset' );
const subset = ~subsetIndex ? process.argv[ subsetIndex + 1 ].split( ',' ).map( file => `${file}.js` ) : null;
const subsetFilter = subset ? file => ~subset.indexOf( file ) : () => true;

describe( 'buble', () => {
	fs.readdirSync( 'test/samples' ).filter( subsetFilter ).forEach( file => {
		if ( !/\.js$/.test( file ) ) return; // avoid vim .js.swp files
		var samples = require( './samples/' + file );

		describe( path.basename( file ), () => {
			samples.forEach( sample => {
				( sample.solo ? it.only : sample.skip ? it.skip : it )( sample.description, () => {
					if ( sample.error ) {
						assert.throws( () => {
							buble.transform( sample.input, sample.options );
						}, sample.error );
					}

					else {
						equal( buble.transform( sample.input, sample.options  ).code, sample.output );
					}
				});
			});
		});
	});

	if ( subset ) return;

	describe( 'cli', () => {
		fs.readdirSync( 'test/cli' ).forEach( dir => {
			if ( dir[0] === '.' ) return; // .DS_Store

			it( dir, done => {
				dir = path.resolve( 'test/cli', dir );
				rimraf.sync( path.resolve( dir, 'actual' ) );
				fs.mkdirSync( path.resolve( dir, 'actual' ) );

				var binFile = path.resolve(__dirname, '../bin/buble');
				var commandFile = path.resolve( dir, 'command.sh' );

				var command = fs.readFileSync( commandFile, 'utf-8' )
					.replace( 'buble', 'node "' + binFile + '"' );
				child_process.exec( command, {
					cwd: dir
				}, ( err, stdout, stderr ) => {
					if ( err ) return done( err );

					if ( stdout ) console.log( stdout );
					if ( stderr ) console.error( stderr );

					function catalogue ( subdir ) {
						subdir = path.resolve( dir, subdir );

						return glob.sync( '**/*.js?(.map)', { cwd: subdir })
							.sort()
							.map( name => {
								var contents = fs.readFileSync( path.resolve( subdir, name ), 'utf-8' ).trim();

								if ( path.extname( name ) === '.map' ) {
									contents = JSON.parse( contents );
								}

								return {
									name: name,
									contents: contents.replace(/\r\n/g, '\n')
								};
							});
					}

					var expected = catalogue( 'expected' );
					var actual = catalogue( 'actual' );

					try {
						assert.deepEqual( actual, expected );
						done();
					} catch ( err ) {
						done( err );
					}
				});
			});
		});
	});

	describe( 'errors', () => {
		it( 'reports the location of a syntax error', () => {
			var source = `var 42 = nope;`;

			try {
				buble.transform( source );
			} catch ( err ) {
				assert.equal( err.name, 'SyntaxError' );
				assert.deepEqual( err.loc, { line: 1, column: 4 });
				assert.equal( err.message, 'Unexpected token (1:4)' );
				assert.equal( err.snippet, `1 : var 42 = nope;\n        ^` );
				assert.equal( err.toString(), `SyntaxError: Unexpected token (1:4)\n1 : var 42 = nope;\n        ^` );
			}
		});

		it( 'reports the location of a compile error', () => {
			var source = `const x = 1; x++;`;

			try {
				buble.transform( source );
			} catch ( err ) {
				assert.equal( err.name, 'CompileError' );
				assert.equal( err.loc.line, 1 );
				assert.equal( err.loc.column, 13 );
				assert.equal( err.message, 'x is read-only (1:13)' );
				assert.equal( err.snippet, `1 : const x = 1; x++;\n                 ^^^` );
				assert.equal( err.toString(), `CompileError: x is read-only (1:13)\n1 : const x = 1; x++;\n                 ^^^` );
			}
		});
	});

	describe( 'target', () => {
		it( 'determines necessary transforms for a target environment', () => {
			var transforms = buble.target({ chrome: 49 });

			assert.ok( transforms.moduleImport );
			assert.ok( !transforms.arrow );
		});

		it( 'returns lowest common denominator support info', () => {
			var transforms = buble.target({ chrome: 49, node: 5 });

			assert.ok( transforms.defaultParameter );
			assert.ok( !transforms.arrow );
		});

		it( 'only applies necessary transforms', () => {
			var source = `
				const power = ( base, exponent = 2 ) => Math.pow( base, exponent );`;

			var result = buble.transform( source, {
				target: { chrome: 49, node: 5 }
			}).code;

			assert.equal( result, `
				const power = ( base, exponent ) => {
					if ( exponent === void 0 ) exponent = 2;

					return Math.pow( base, exponent );
				};` );
		});
	});

	describe( 'sourcemaps', () => {
		it( 'generates a valid sourcemap', () => {
			var map = buble.transform( '' ).map;
			assert.equal( map.version, 3 );
		});

		it( 'uses provided file and source', () => {
			var map = buble.transform( '', {
				file: 'output.js',
				source: 'input.js'
			}).map;

			assert.equal( map.file, 'output.js' );
			assert.deepEqual( map.sources, [ 'input.js' ] );
		});

		it( 'includes content by default', () => {
			var source = `let { x, y } = foo();`;
			var map = buble.transform( source ).map;

			assert.deepEqual( map.sourcesContent, [ source ] );
		});

		it( 'excludes content if requested', () => {
			var source = `let { x, y } = foo();`;
			var map = buble.transform( source, {
				includeContent: false
			}).map;

			assert.deepEqual( map.sourcesContent, [ null ] );
		});

		it( 'locates original content', () => {
			var source = `const add = ( a, b ) => a + b;`;
			var result = buble.transform( source, {
				file: 'output.js',
				source: 'input.js'
			});

			var smc = new SourceMapConsumer( result.map );

			var location = getLocation( result.code, 'add' );
			var expected = getLocation( source, 'add' );

			var actual = smc.originalPositionFor( location );

			assert.deepEqual( actual, {
				line: expected.line,
				column: expected.column,
				source: 'input.js',
				name: null
			});

			location = getLocation( result.code, 'a +' );
			expected = getLocation( source, 'a +' );

			actual = smc.originalPositionFor( location );

			assert.deepEqual( actual, {
				line: expected.line,
				column: expected.column,
				source: 'input.js',
				name: null
			});
		});

		it( 'recovers names', () => {
			var source = `
				const foo = 1;
				if ( x ) {
					const foo = 2;
				}`;

			var result = buble.transform( source, {
				file: 'output.js',
				source: 'input.js'
			});
			var smc = new SourceMapConsumer( result.map );

			var location = getLocation( result.code, 'var' );
			var actual = smc.originalPositionFor( location );

			assert.equal( actual.name, 'const' );

			location = getLocation( result.code, 'var', location.char + 1 );
			actual = smc.originalPositionFor( location );

			assert.equal( actual.name, 'const' );

			location = getLocation( result.code, 'foo$1', location.char + 1 );
			actual = smc.originalPositionFor( location );

			assert.equal( actual.name, 'foo' );
		});

		it( 'handles moved content', () => {
			var source = `
				for ( let i = 0; i < 10; i += 1 ) {
					const square = i * i;
					setTimeout( function () {
						log( square );
					}, i * 100 );
				}`;

			var result = buble.transform( source, {
				file: 'output.js',
				source: 'input.js'
			});
			var smc = new SourceMapConsumer( result.map );

			var location = getLocation( result.code, 'i < 10' );
			var expected = getLocation( source, 'i < 10' );

			var actual = smc.originalPositionFor( location );

			assert.deepEqual( actual, {
				line: expected.line,
				column: expected.column,
				source: 'input.js',
				name: null
			});

			location = getLocation( result.code, 'setTimeout' );
			expected = getLocation( source, 'setTimeout' );

			actual = smc.originalPositionFor( location );

			assert.deepEqual( actual, {
				line: expected.line,
				column: expected.column,
				source: 'input.js',
				name: null
			});
		});
	});
});
<|endoftext|>


<commit_before>var assert = require('assert'),
    objm = require('../')

assert.deepEqual(objm(), {})
assert.deepEqual(objm({ hey: 'woo' }), { hey: 'woo' })
assert.deepEqual(objm({ hey: 'woo' }, { hey: 'wee' }), { hey: ['woo', 'wee'] })
assert.deepEqual(objm({ a: [1, 2] }, { a: [3, 4], b: 0 }), { a: [1, 2, 3, 4], b: 0 })
<commit_msg>good good good<commit_after>var assert = require('assert'),
    objm = require('../')

assert.deepEqual(objm(), {})
assert.deepEqual(objm({ hey: 'woo' }), { hey: 'woo' })
assert.deepEqual(objm({ hey: 'woo' }, { hey: 'wee' }), { hey: ['woo', 'wee'] })
assert.deepEqual(objm({ a: [1, 2] }, { a: [3, 4], b: 0 }), { a: [1, 2, 3, 4], b: 0 })
assert.deepEqual(objm({ a: [0] }, { a: [1] }, { a: [2] }, { a: [3, 4] }, { a: 5 }), { a: [0, 1, 2, 3, 4, 5] })
<|endoftext|>


<commit_before>'use strict';

/*jshint expr: true*/
var should = require('chai').should();
var _ = require('underscore');
var Player = require('../player');
var dummyBackend = require('nodeplayer-backend-dummy');
var exampleQueue = require('./exampleQueue.json');

process.env.NODE_ENV = 'test';

var dummyLogger = {
    silly: _.noop,
    debug: _.noop,
    verbose: _.noop,
    info: _.noop,
    warn: _.noop,
    error: _.noop,
};

describe('exampleQueue', function() {
    it('should contain at least 5 items', function() {
        exampleQueue.length.should.be.above(5);
    });
});

// TODO: test error cases also
describe('Player', function() {
    describe('#setVolume()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
        });
        it('should set volume to 1 by default', function() {
            player.volume.should.equal(1).and.be.a('number');
        });
        it('should set volume to 0 for negative values', function() {
            player.setVolume(-1);
            player.volume.should.equal(0).and.be.a('number');
        });
        it('should set volume to 1 for values greater than 1', function() {
            player.setVolume(42);
            player.volume.should.equal(1).and.be.a('number');
        });
        it('should set volume to 0.5', function() {
            player.setVolume(0.5);
            player.volume.should.equal(0.5).and.be.a('number');
        });
    });

    describe('#skipSongs()', function() {
        var player;
        var playedQueueSize = 3; // TODO: better handling of config variables here

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            player.queue = _.clone(exampleQueue);
            player.config.playedQueueSize = playedQueueSize;
            player.prepareSongs = _.noop;
        });
        it('should put a skipped song into playedQueue', function() {
            player.skipSongs(1);
            _.last(player.playedQueue).should.deep.equal(_.first(exampleQueue));
        });
        it('should put multiple skipped songs into playedQueue', function() {
            player.skipSongs(2);
            _.last(player.playedQueue, 2).should.deep.equal(_.first(exampleQueue, 2));
        });
        it('should put up to playedQueueSize songs into playedQueue ' +
                'if skipping by a large amount', function() {
            player.skipSongs(exampleQueue.length + 100);
            player.playedQueue.should.deep.equal(_.last(exampleQueue, playedQueueSize));
        });
        it('should put last song from playedQueue into queue ' +
                'when skipping to prev song', function() {
            player.skipSongs(exampleQueue.length + 100);
            player.skipSongs(-1);
            _.first(player.queue).should.deep.equal(_.last(exampleQueue));
        });
        it('should put up to playedQueueSize songs from playedQueue into queue ' +
                'when skipping to prev songs', function() {
            player.skipSongs(exampleQueue.length + 100);
            player.skipSongs((playedQueueSize + 100) * -1);
            player.queue.should.deep.equal(_.last(exampleQueue, playedQueueSize));
        });
    });

    describe('#shuffleQueue()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            player.queue = _.clone(exampleQueue);
            player.prepareSongs = _.noop;
        });
        it('should not change the now playing song', function() {
            for (var i = 0; i < 10; i++) {
                // no matter how many times we shuffle :-)
                player.shuffleQueue();
                _.first(player.queue).should.deep.equal(_.first(exampleQueue));
            }
        });
    });
    describe('#addToQueue()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            player.prepareSongs = _.noop;
        });
        it('should not add song if required fields are not provided', function() {
            player.addToQueue([{title: 'foo', songID: 'bar', backendName: 'baz'}]);
            player.addToQueue([{title: 'foo', songID: 'bar', duration: 42}]);
            player.addToQueue([{title: 'foo', backendName: 'bar', duration: 42}]);
            player.addToQueue([{songID: 'foo', backendName: 'bar', duration: 42}]);
            player.queue.length.should.equal(0);
        });
        it('should add song correctly', function() {
            player.addToQueue([_.first(exampleQueue)]);
            _.first(player.queue).should.deep.equal(_.first(exampleQueue));
        });
        it('should add multiple songs correctly', function() {
            player.addToQueue(_.first(exampleQueue, 3));
            player.queue.should.deep.equal(_.first(exampleQueue, 3));
        });
        it('should add song to provided position', function() {
            player.addToQueue(_.first(exampleQueue, 3));
            player.addToQueue([exampleQueue[3]], 1);
            player.queue.should.deep.equal([
                exampleQueue[0],
                exampleQueue[3],
                exampleQueue[1],
                exampleQueue[2]
            ]);
        });
        it('should add multiple songs to provided position', function() {
            player.addToQueue(_.first(exampleQueue, 3));
            player.addToQueue(_.last(exampleQueue, 2), 1);
            player.queue.should.deep.equal([
                exampleQueue[0],
                exampleQueue[exampleQueue.length - 2],
                exampleQueue[exampleQueue.length - 1],
                exampleQueue[1],
                exampleQueue[2]
            ]);
        });
        it('should add song to end of queue if provided position is huge', function() {
            player.addToQueue(_.first(exampleQueue, 3));
            player.addToQueue([_.last(exampleQueue)], 100000);
            player.queue.should.deep.equal([
                exampleQueue[0],
                exampleQueue[1],
                exampleQueue[2],
                exampleQueue[exampleQueue.length - 1]
            ]);
        });
        it('should add song to beginning of queue (not replacing now playing!) ' +
                'if provided position is negative', function() {
            player.addToQueue(_.first(exampleQueue, 3));
            player.addToQueue([_.last(exampleQueue)], -100000);
            player.queue.should.deep.equal([
                exampleQueue[0],
                exampleQueue[exampleQueue.length - 1],
                exampleQueue[1],
                exampleQueue[2]
            ]);
        });
    });
    describe('#removeFromQueue()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            player.queue = _.clone(exampleQueue);
            player.prepareSongs = _.noop;
        });
        it('should remove song from provided pos', function() {
            player.removeFromQueue(1);
            player.queue.should.deep.equal(_.without(exampleQueue, exampleQueue[1]));
        });
        it('should remove now playing if pos is 0', function() {
            player.removeFromQueue(0);
            player.queue.should.deep.equal(_.without(exampleQueue, exampleQueue[0]));
        });
        it('should remove multiple songs from provided pos', function() {
            player.removeFromQueue(1, 2);
            player.queue.should.deep.equal(_.without(
                exampleQueue,
                exampleQueue[1],
                exampleQueue[2]
            ));
        });
        it('should remove songs from playedQueue with negative provided pos', function() {
            player.skipSongs(2);
            player.removeFromQueue(-1, 1);
            player.playedQueue.should.deep.equal([exampleQueue[0]]);
        });
        it('should correctly remove songs from both queue and playedQueue ' +
                'with negative provided pos and cnt (range) spanning both queues', function() {
            player.skipSongs(2);
            player.removeFromQueue(-1, 3);
            player.playedQueue.should.deep.equal([exampleQueue[0]]);
            /* magic number 4 comes from skipping *2* and removing 3 songs
             * from index -1, removing *2* songs from the queue */
            player.queue.should.deep.equal(_.last(exampleQueue, exampleQueue.length - 4));
        });
    });
    describe('#searchQueue()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            player.queue = _.clone(exampleQueue);
        });
        it('should return correct song from queue', function() {
            player.searchQueue(exampleQueue[2].backendName, exampleQueue[2].songID)
            .should.deep.equal(exampleQueue[2]);
        });
        it('should return null for bogus terms', function() {
            (player.searchQueue('thisBackendShouldNotExist', 'thisSongIdShouldNotExist') === null)
            .should.equal(true);
        });
    });
    describe('#onQueueModify()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            player.queue = _.clone(exampleQueue);
            player.prepareSongs = _.noop;
        });
        it('should move next song to now playing if there is no now playing song', function() {
            player.queue[0] = null;
            player.onQueueModify();
            _.first(player.queue).should.deep.equal(exampleQueue[1]);
        });
    });
    describe('#searchBackends()', function() {
        var player;
        var dummyResults;

        beforeEach(function(done) {
            player = new Player({logger: dummyLogger});
            dummyBackend.init(player, dummyLogger, _.noop);
            player.backends.dummyBackend = dummyBackend;
            player.songsPreparing.dummyBackend = {};

            dummyBackend.search({terms: 'dummySearch'}, function(results) {
                dummyResults = {dummy: results};
                done();
            });
        });
        it('should return same results as dummy backend', function(done) {
            player.searchBackends({terms: 'dummySearch'}, function(results) {
                results.should.deep.equal(dummyResults);
                done();
            });
        });
        it('should return empty object if backend errors', function(done) {
            player.searchBackends({terms: 'shouldCauseError'}, function(results) {
                results.should.deep.equal({});
                done();
            });
        });
    });
    describe('#prepareSong()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            dummyBackend.init(player, dummyLogger, _.noop);
            player.backends.dummyBackend = dummyBackend;
            player.songsPreparing.dummyBackend = {};

            player.startPlayback = _.noop;
        });
        it('should return truthy value (error) if called without song', function(done) {
            player.prepareSong(undefined, function(err) {
                err.should.be.ok;
                done();
            });
        });
        it('should call startPlayback and return falsy value ' +
                'on first queue item if prepared', function(done) {
            player.queue = _.clone(exampleQueue);
            player.queue[0].songID = 'shouldBePrepared';

            var startPlaybackWasCalled = false;
            player.startPlayback = function() {
                startPlaybackWasCalled = true;
            };

            player.prepareSong(player.queue[0], function(err) {
                startPlaybackWasCalled.should.equal(true);
                (!err).should.be.ok;
                done();
            });
        });
        it('should return truthy value if song already preparing', function(done) {
            player.queue = _.clone(exampleQueue);

            player.queue[0].songID = 'shouldPrepareForever';

            player.prepareSong(player.queue[0]);
            player.prepareSong(player.queue[0], function(err) {
                err.should.be.ok;
                done();
            });
        });
    });
});
<commit_msg>oops, fix the build again<commit_after>'use strict';

/*jshint expr: true*/
var should = require('chai').should();
var _ = require('underscore');
var Player = require('../player');
var dummyBackend = require('nodeplayer-backend-dummy');
var exampleQueue = require('./exampleQueue.json');

process.env.NODE_ENV = 'test';

var dummyLogger = {
    silly: _.noop,
    debug: _.noop,
    verbose: _.noop,
    info: _.noop,
    warn: _.noop,
    error: _.noop,
};

describe('exampleQueue', function() {
    it('should contain at least 5 items', function() {
        exampleQueue.length.should.be.above(5);
    });
});

// TODO: test error cases also
describe('Player', function() {
    describe('#setVolume()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
        });
        it('should set volume to 1 by default', function() {
            player.volume.should.equal(1).and.be.a('number');
        });
        it('should set volume to 0 for negative values', function() {
            player.setVolume(-1);
            player.volume.should.equal(0).and.be.a('number');
        });
        it('should set volume to 1 for values greater than 1', function() {
            player.setVolume(42);
            player.volume.should.equal(1).and.be.a('number');
        });
        it('should set volume to 0.5', function() {
            player.setVolume(0.5);
            player.volume.should.equal(0.5).and.be.a('number');
        });
    });

    describe('#skipSongs()', function() {
        var player;
        var playedQueueSize = 3; // TODO: better handling of config variables here

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            player.queue = _.clone(exampleQueue);
            player.config.playedQueueSize = playedQueueSize;
            player.prepareSongs = _.noop;
        });
        it('should put a skipped song into playedQueue', function() {
            player.skipSongs(1);
            _.last(player.playedQueue).should.deep.equal(_.first(exampleQueue));
        });
        it('should put multiple skipped songs into playedQueue', function() {
            player.skipSongs(2);
            _.last(player.playedQueue, 2).should.deep.equal(_.first(exampleQueue, 2));
        });
        it('should put up to playedQueueSize songs into playedQueue ' +
                'if skipping by a large amount', function() {
            player.skipSongs(exampleQueue.length + 100);
            player.playedQueue.should.deep.equal(_.last(exampleQueue, playedQueueSize));
        });
        it('should put last song from playedQueue into queue ' +
                'when skipping to prev song', function() {
            player.skipSongs(exampleQueue.length + 100);
            player.skipSongs(-1);
            _.first(player.queue).should.deep.equal(_.last(exampleQueue));
        });
        it('should put up to playedQueueSize songs from playedQueue into queue ' +
                'when skipping to prev songs', function() {
            player.skipSongs(exampleQueue.length + 100);
            player.skipSongs((playedQueueSize + 100) * -1);
            player.queue.should.deep.equal(_.last(exampleQueue, playedQueueSize));
        });
    });

    describe('#shuffleQueue()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            player.queue = _.clone(exampleQueue);
            player.prepareSongs = _.noop;
        });
        it('should not change the now playing song', function() {
            for (var i = 0; i < 10; i++) {
                // no matter how many times we shuffle :-)
                player.shuffleQueue();
                _.first(player.queue).should.deep.equal(_.first(exampleQueue));
            }
        });
    });
    describe('#addToQueue()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            player.prepareSongs = _.noop;
        });
        it('should not add song if required fields are not provided', function() {
            player.addToQueue([{title: 'foo', songID: 'bar', backendName: 'baz'}]);
            player.addToQueue([{title: 'foo', songID: 'bar', duration: 42}]);
            player.addToQueue([{title: 'foo', backendName: 'bar', duration: 42}]);
            player.addToQueue([{songID: 'foo', backendName: 'bar', duration: 42}]);
            player.queue.length.should.equal(0);
        });
        it('should add song correctly', function() {
            player.addToQueue([_.first(exampleQueue)]);
            _.first(player.queue).should.deep.equal(_.first(exampleQueue));
        });
        it('should add multiple songs correctly', function() {
            player.addToQueue(_.first(exampleQueue, 3));
            player.queue.should.deep.equal(_.first(exampleQueue, 3));
        });
        it('should add song to provided position', function() {
            player.addToQueue(_.first(exampleQueue, 3));
            player.addToQueue([exampleQueue[3]], 1);
            player.queue.should.deep.equal([
                exampleQueue[0],
                exampleQueue[3],
                exampleQueue[1],
                exampleQueue[2]
            ]);
        });
        it('should add multiple songs to provided position', function() {
            player.addToQueue(_.first(exampleQueue, 3));
            player.addToQueue(_.last(exampleQueue, 2), 1);
            player.queue.should.deep.equal([
                exampleQueue[0],
                exampleQueue[exampleQueue.length - 2],
                exampleQueue[exampleQueue.length - 1],
                exampleQueue[1],
                exampleQueue[2]
            ]);
        });
        it('should add song to end of queue if provided position is huge', function() {
            player.addToQueue(_.first(exampleQueue, 3));
            player.addToQueue([_.last(exampleQueue)], 100000);
            player.queue.should.deep.equal([
                exampleQueue[0],
                exampleQueue[1],
                exampleQueue[2],
                exampleQueue[exampleQueue.length - 1]
            ]);
        });
        it('should add song to beginning of queue (not replacing now playing!) ' +
                'if provided position is negative', function() {
            player.addToQueue(_.first(exampleQueue, 3));
            player.addToQueue([_.last(exampleQueue)], -100000);
            player.queue.should.deep.equal([
                exampleQueue[0],
                exampleQueue[exampleQueue.length - 1],
                exampleQueue[1],
                exampleQueue[2]
            ]);
        });
    });
    describe('#removeFromQueue()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            player.queue = _.clone(exampleQueue);
            player.prepareSongs = _.noop;
        });
        it('should remove song from provided pos', function() {
            player.removeFromQueue(1);
            player.queue.should.deep.equal(_.without(exampleQueue, exampleQueue[1]));
        });
        it('should remove now playing if pos is 0', function() {
            player.removeFromQueue(0);
            player.queue.should.deep.equal(_.without(exampleQueue, exampleQueue[0]));
        });
        it('should remove multiple songs from provided pos', function() {
            player.removeFromQueue(1, 2);
            player.queue.should.deep.equal(_.without(
                exampleQueue,
                exampleQueue[1],
                exampleQueue[2]
            ));
        });
        it('should remove songs from playedQueue with negative provided pos', function() {
            player.skipSongs(2);
            player.removeFromQueue(-1, 1);
            player.playedQueue.should.deep.equal([exampleQueue[0]]);
        });
        it('should correctly remove songs from both queue and playedQueue ' +
                'with negative provided pos and cnt (range) spanning both queues', function() {
            player.skipSongs(2);
            player.removeFromQueue(-1, 3);
            player.playedQueue.should.deep.equal([exampleQueue[0]]);
            /* magic number 4 comes from skipping *2* and removing 3 songs
             * from index -1, removing *2* songs from the queue */
            player.queue.should.deep.equal(_.last(exampleQueue, exampleQueue.length - 4));
        });
    });
    describe('#searchQueue()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            player.queue = _.clone(exampleQueue);
        });
        it('should return correct song from queue', function() {
            player.searchQueue(exampleQueue[2].backendName, exampleQueue[2].songID)
            .should.deep.equal(exampleQueue[2]);
        });
        it('should return null for bogus terms', function() {
            (player.searchQueue('thisBackendShouldNotExist', 'thisSongIdShouldNotExist') === null)
            .should.equal(true);
        });
    });
    describe('#onQueueModify()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            player.queue = _.clone(exampleQueue);
            player.prepareSongs = _.noop;
        });
        it('should move next song to now playing if there is no now playing song', function() {
            player.queue[0] = null;
            player.onQueueModify();
            _.first(player.queue).should.deep.equal(exampleQueue[1]);
        });
    });
    describe('#searchBackends()', function() {
        var player;
        var dummyResults;

        beforeEach(function(done) {
            player = new Player({logger: dummyLogger});
            dummyBackend.init(player, dummyLogger, _.noop);
            player.backends.dummyBackend = dummyBackend;
            player.songsPreparing.dummyBackend = {};

            dummyBackend.search({terms: 'dummySearch'}, function(results) {
                dummyResults = {dummy: results};
                done();
            });
        });
        it('should return same results as dummy backend', function(done) {
            player.searchBackends({terms: 'dummySearch'}, function(results) {
                results.should.deep.equal(dummyResults);
                done();
            });
        });
        it('should return empty object if backend errors', function(done) {
            player.searchBackends({terms: 'shouldCauseError'}, function(results) {
                results.should.deep.equal({});
                done();
            });
        });
    });
    describe('#prepareSong()', function() {
        var player;

        beforeEach(function() {
            player = new Player({logger: dummyLogger});
            dummyBackend.init(player, dummyLogger, _.noop);
            player.backends.dummyBackend = dummyBackend;
            player.songsPreparing.dummyBackend = {};

            player.startPlayback = _.noop;
        });
        it('should return truthy value (error) if called without song', function(done) {
            player.prepareSong(undefined, function(err) {
                err.should.be.ok;
                done();
            });
        });
        it('should call startPlayback and return falsy value ' +
                'on first queue item if prepared', function(done) {
            player.queue = _.clone(exampleQueue);
            player.queue[0].songID = 'shouldBePrepared';

            var startPlaybackWasCalled = false;
            player.startPlayback = function() {
                startPlaybackWasCalled = true;
            };

            player.prepareSong(player.queue[0], function(err) {
                startPlaybackWasCalled.should.equal(true);
                (!err).should.be.ok;
                done();
            });
        });
        it('should return truthy value if song already preparing', function(done) {
            player.queue = _.clone(exampleQueue);

            player.queue[0].songID = 'shouldPrepareForever';

            player.prepareSong(player.queue[0], _.noop);
            player.prepareSong(player.queue[0], function(err) {
                err.should.be.ok;
                done();
            });
        });
    });
});
<|endoftext|>


<commit_before>'use strict';

var test = require('tape');

var React = require('react/addons');
var TestUtils = React.addons.TestUtils;

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

test('component basics', (t) => {

  let onChangeObj;
  function _onChange(color) {
    onChangeObj = color;
  }

  function find(className) {
    return TestUtils.findRenderedDOMComponentWithClass(colorpickr, className).getDOMNode();
  }

  const colorpickr = TestUtils.renderIntoDocument(
    <Colorpickr onChange={_onChange} />
  );

  t.ok(colorpickr, 'colorpickr component is rendered in document');

  const r = find('rgb-attribute-r');
  const g = find('rgb-attribute-g');
  const b = find('rgb-attribute-b');

  const hex = find('cp-hex-input');

  const HSVTab = find('cp-mode-hsv');
  const colorSlider = find('cp-colormode-slider');

  const colorSliderInput = find('cp-colormode-slider-input');
  const alphaSliderInput = find('cp-alpha-slider-input');

  // Default options are intact
  const reset = find('cp-swatch-reset');
  t.ok(reset, 'Reset option is present by default');

  t.equal(hex.value, '3887be', 'default HEX value is present');

  // TEST RGB MODE
  r.value = 255;
  TestUtils.Simulate.change(r);
  TestUtils.Simulate.focus(r);
  t.equal(colorSlider.classList.contains('r'), true, 'slider for RGB (r) is present when RGB (r) input is in focus.');

  g.value = 255;
  TestUtils.Simulate.change(g);
  TestUtils.Simulate.focus(g);
  t.equal(colorSlider.classList.contains('g'), true, 'slider for RGB (g) is present when RGB (g) input is in focus.');

  b.value = 255;
  TestUtils.Simulate.change(b);
  TestUtils.Simulate.focus(b);
  t.equal(colorSlider.classList.contains('b'), true, 'slider for RGB (b) is present when RGB (g) input is in focus.');

  t.equal(hex.value, 'ffffff', 'RGB inputs update HEX to #ffffff');

  // SWITCH TO HSV MODE
  TestUtils.Simulate.click(HSVTab);
  t.equal(HSVTab.classList.contains('cp-active'), true, 'HSV tab is active');

  const h = find('hsv-attribute-h');
  const s = find('hsv-attribute-s');
  const v = find('hsv-attribute-v');

  t.equal(h.value, '0', 'HSV attribute H is present and its value onChange');
  t.equal(s.value, '0', 'HSV attribute S is present and its value onChange');
  t.equal(v.value, '100', 'HSV attribute V is present and its value onChange');

  TestUtils.Simulate.focus(h);
  t.equal(colorSlider.classList.contains('h'), true, 'slider for hue is present when HSV (h) input is in focus.');

  TestUtils.Simulate.focus(s);
  t.equal(colorSlider.classList.contains('s'), true, 'slider for saturation is present when HSV (s) input is in focus.');

  TestUtils.Simulate.focus(v);
  t.equal(colorSlider.classList.contains('v'), true, 'slider for value is present when HSV (v) input is in focus.');

  colorSliderInput.value = 0;
  TestUtils.Simulate.change(colorSliderInput);

  t.equal(v.value, '0', 'HSV (v) input attribute changed to 0 after adjusting the color slider');
  TestUtils.Simulate.change(v);

  t.equal(hex.value, '000000', 'input updates HEX to #000000');

  alphaSliderInput.value = 50;
  TestUtils.Simulate.change(alphaSliderInput);
  t.equal(onChangeObj.a, 0.5, 'alpha output is adjusted');

  t.end();
});

test('component options', (t) => {

  let onChangeObj;
  function _onChange(color) {
    onChangeObj = color;
  }

  function find(className) {
    return TestUtils.findRenderedDOMComponentWithClass(colorpickr, className).getDOMNode();
  }

  const colorpickr = TestUtils.renderIntoDocument(
    <Colorpickr
      reset={false}
      colorAttribute={'g'}
      mode={'hsv'}
      value={'#000'}
      onChange={_onChange}
    />
  );

  t.ok(colorpickr, 'colorpickr component with options is rendered in document');

  const reset = TestUtils.scryRenderedDOMComponentsWithClass(colorpickr, 'cp-swatch-reset');
  t.notOk(reset.length > 0, 'Reset is not present when false is passed');

  const colorSlider = find('cp-colormode-slider');
  t.equal(colorSlider.classList.contains('g'), true, 'Color attribute RGB (g) is active');

  const h = find('hsv-attribute-h');
  t.ok(h, 'Hue attribute element is present which means its tab is open');

  const hex = find('cp-hex-input');
  t.equal(hex.value, '000', 'Hex value is equal to value passed');
  TestUtils.Simulate.change(hex);

  const expectOnChangeToBe = {
    h: 0,
    s: 0,
    v: 0,
    r: 0,
    g: 0,
    b: 0,
    a: 1,
    hex: '000',
    input: 'hex',
    mode: 'hsv',
    colorAttribute: 'g'
  };

  t.deepEqual(onChangeObj, expectOnChangeToBe, 'onChange object reflects options passed');
  t.end();
});

test('rgb value', (t) => {

  let onChangeObj;
  function _onChange(color) {
    onChangeObj = color;
  }

  const colorpickr = TestUtils.renderIntoDocument(
    <Colorpickr
      value={'rgb(0,255,255)'}
      onChange={_onChange}
    />
  );

  t.ok(colorpickr, 'colorpickr component with options is rendered in document');

  TestUtils.Simulate.change(TestUtils.findRenderedDOMComponentWithClass(colorpickr, 'cp-hex-input').getDOMNode());

  const expectOnChangeToBe = {
    h: 180,
    s: 100,
    v: 100,
    r: 0,
    g: 255,
    b: 255,
    a: 1,
    hex: '0ff',
    input: 'hex',
    mode: 'rgb',
    colorAttribute: 'h'
  };

  t.deepEqual(onChangeObj, expectOnChangeToBe, 'onChange object reflects options passed');
  t.end();
});

test('rgba value', (t) => {

  let onChangeObj;
  function _onChange(color) {
    onChangeObj = color;
  }

  const colorpickr = TestUtils.renderIntoDocument(
    <Colorpickr
      value={'rgba(0,255,255,0.5)'}
      onChange={_onChange}
    />
  );

  t.ok(colorpickr, 'colorpickr component with options is rendered in document');

  TestUtils.Simulate.change(TestUtils.findRenderedDOMComponentWithClass(colorpickr, 'cp-hex-input').getDOMNode());

  const expectOnChangeToBe = {
    h: 180,
    s: 100,
    v: 100,
    r: 0,
    g: 255,
    b: 255,
    a: 0.5,
    hex: '0ff',
    mode: 'rgb',
    input: 'hex',
    colorAttribute: 'h'
  };

  t.deepEqual(onChangeObj, expectOnChangeToBe, 'onChange object reflects options passed');
  t.end();
});

// close the smokestack window once tests are complete
test('shutdown', function(t) {
  t.end();
  setTimeout(function() {
    window.close();
  });
});
<commit_msg>`change` is no longer the change event in react-slider. Simulate a change with a click instead<commit_after>'use strict';

var test = require('tape');

var React = require('react/addons');
var TestUtils = React.addons.TestUtils;

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

test('component basics', (t) => {

  let onChangeObj;
  function _onChange(color) {
    onChangeObj = color;
  }

  function find(className) {
    return TestUtils.findRenderedDOMComponentWithClass(colorpickr, className).getDOMNode();
  }

  const colorpickr = TestUtils.renderIntoDocument(
    <Colorpickr onChange={_onChange} />
  );

  t.ok(colorpickr, 'colorpickr component is rendered in document');

  const r = find('rgb-attribute-r');
  const g = find('rgb-attribute-g');
  const b = find('rgb-attribute-b');

  const hex = find('cp-hex-input');

  const HSVTab = find('cp-mode-hsv');
  const colorSlider = find('cp-colormode-slider');

  const colorSliderInput = find('cp-colormode-slider-input');
  const alphaSliderInput = find('cp-alpha-slider-input');

  // Default options are intact
  const reset = find('cp-swatch-reset');
  t.ok(reset, 'Reset option is present by default');

  t.equal(hex.value, '3887be', 'default HEX value is present');

  // TEST RGB MODE
  r.value = 255;
  TestUtils.Simulate.change(r);
  TestUtils.Simulate.focus(r);
  t.equal(colorSlider.classList.contains('r'), true, 'slider for RGB (r) is present when RGB (r) input is in focus.');

  g.value = 255;
  TestUtils.Simulate.change(g);
  TestUtils.Simulate.focus(g);
  t.equal(colorSlider.classList.contains('g'), true, 'slider for RGB (g) is present when RGB (g) input is in focus.');

  b.value = 255;
  TestUtils.Simulate.change(b);
  TestUtils.Simulate.focus(b);
  t.equal(colorSlider.classList.contains('b'), true, 'slider for RGB (b) is present when RGB (g) input is in focus.');

  t.equal(hex.value, 'ffffff', 'RGB inputs update HEX to #ffffff');

  // SWITCH TO HSV MODE
  TestUtils.Simulate.click(HSVTab);
  t.equal(HSVTab.classList.contains('cp-active'), true, 'HSV tab is active');

  const h = find('hsv-attribute-h');
  const s = find('hsv-attribute-s');
  const v = find('hsv-attribute-v');

  t.equal(h.value, '0', 'HSV attribute H is present and its value onChange');
  t.equal(s.value, '0', 'HSV attribute S is present and its value onChange');
  t.equal(v.value, '100', 'HSV attribute V is present and its value onChange');

  TestUtils.Simulate.focus(h);
  t.equal(colorSlider.classList.contains('h'), true, 'slider for hue is present when HSV (h) input is in focus.');

  TestUtils.Simulate.focus(s);
  t.equal(colorSlider.classList.contains('s'), true, 'slider for saturation is present when HSV (s) input is in focus.');

  TestUtils.Simulate.focus(v);
  t.equal(colorSlider.classList.contains('v'), true, 'slider for value is present when HSV (v) input is in focus.');

  colorSliderInput.value = 0;
  TestUtils.Simulate.click(colorSliderInput);

  t.equal(v.value, '0', 'HSV (v) input attribute changed to 0 after adjusting the color slider');
  TestUtils.Simulate.click(v);

  t.equal(hex.value, '000000', 'input updates HEX to #000000');

  alphaSliderInput.value = 50;
  TestUtils.Simulate.click(alphaSliderInput);
  t.equal(onChangeObj.a, 0.5, 'alpha output is adjusted');

  t.end();
});

test('component options', (t) => {

  let onChangeObj;
  function _onChange(color) {
    onChangeObj = color;
  }

  function find(className) {
    return TestUtils.findRenderedDOMComponentWithClass(colorpickr, className).getDOMNode();
  }

  const colorpickr = TestUtils.renderIntoDocument(
    <Colorpickr
      reset={false}
      colorAttribute={'g'}
      mode={'hsv'}
      value={'#000'}
      onChange={_onChange}
    />
  );

  t.ok(colorpickr, 'colorpickr component with options is rendered in document');

  const reset = TestUtils.scryRenderedDOMComponentsWithClass(colorpickr, 'cp-swatch-reset');
  t.notOk(reset.length > 0, 'Reset is not present when false is passed');

  const colorSlider = find('cp-colormode-slider');
  t.equal(colorSlider.classList.contains('g'), true, 'Color attribute RGB (g) is active');

  const h = find('hsv-attribute-h');
  t.ok(h, 'Hue attribute element is present which means its tab is open');

  const hex = find('cp-hex-input');
  t.equal(hex.value, '000', 'Hex value is equal to value passed');
  TestUtils.Simulate.change(hex);

  const expectOnChangeToBe = {
    h: 0,
    s: 0,
    v: 0,
    r: 0,
    g: 0,
    b: 0,
    a: 1,
    hex: '000',
    input: 'hex',
    mode: 'hsv',
    colorAttribute: 'g'
  };

  t.deepEqual(onChangeObj, expectOnChangeToBe, 'onChange object reflects options passed');
  t.end();
});

test('rgb value', (t) => {

  let onChangeObj;
  function _onChange(color) {
    onChangeObj = color;
  }

  const colorpickr = TestUtils.renderIntoDocument(
    <Colorpickr
      value={'rgb(0,255,255)'}
      onChange={_onChange}
    />
  );

  t.ok(colorpickr, 'colorpickr component with options is rendered in document');

  TestUtils.Simulate.change(TestUtils.findRenderedDOMComponentWithClass(colorpickr, 'cp-hex-input').getDOMNode());

  const expectOnChangeToBe = {
    h: 180,
    s: 100,
    v: 100,
    r: 0,
    g: 255,
    b: 255,
    a: 1,
    hex: '0ff',
    input: 'hex',
    mode: 'rgb',
    colorAttribute: 'h'
  };

  t.deepEqual(onChangeObj, expectOnChangeToBe, 'onChange object reflects options passed');
  t.end();
});

test('rgba value', (t) => {

  let onChangeObj;
  function _onChange(color) {
    onChangeObj = color;
  }

  const colorpickr = TestUtils.renderIntoDocument(
    <Colorpickr
      value={'rgba(0,255,255,0.5)'}
      onChange={_onChange}
    />
  );

  t.ok(colorpickr, 'colorpickr component with options is rendered in document');

  TestUtils.Simulate.change(TestUtils.findRenderedDOMComponentWithClass(colorpickr, 'cp-hex-input').getDOMNode());

  const expectOnChangeToBe = {
    h: 180,
    s: 100,
    v: 100,
    r: 0,
    g: 255,
    b: 255,
    a: 0.5,
    hex: '0ff',
    mode: 'rgb',
    input: 'hex',
    colorAttribute: 'h'
  };

  t.deepEqual(onChangeObj, expectOnChangeToBe, 'onChange object reflects options passed');
  t.end();
});

// close the smokestack window once tests are complete
test('shutdown', function(t) {
  t.end();
  setTimeout(function() {
    window.close();
  });
});
<|endoftext|>


<commit_before>function traverseDOM(node){
  var childLen=node.childNodes.length;
  if(childLen==0){
  }else{
    for(var i=0;i<childLen;i++){
      var childTmp=node.childNodes[i];
      if(childTmp.nodeType==1){
        if(childTmp.id=='tanx-popwin-outermm_51073678_5024723_15460009'){
          var str="hello world!";
        }
        var obj=window.getComputedStyle(childTmp);
        if(obj.hasOwnProperty("position")){
          if(obj.position=="fixed"){
            console.log("the fixed element");
            console.log(childTmp);
            childTmp.style.display="none";
            return;
          }
        }
      }
      traverseDOM(childTmp);
    }
  }
}

setTimeout(function(){
  traverseDOM(document.body);
},0);

<commit_msg>Update test.js<commit_after>function traverseDOM(node){
  var childLen=node.childNodes.length;
  if(childLen==0){
  }else{
    for(var i=0;i<childLen;i++){
      var childTmp=node.childNodes[i];
      if(childTmp.nodeType==1){
        if(childTmp.id=='tanx-popwin-outermm_51073678_5024723_15460009'){
          var str="hello world!";
        }
        var obj=window.getComputedStyle(childTmp);
        if(obj.hasOwnProperty("position")){
          if(obj.position=="fixed"){
            console.log("the fixed element");
            console.log(childTmp);
            childTmp.style.display="none";
            return;
          }
        }
      }
      traverseDOM(childTmp);
    }
  }
}

setTimeout(function(){
  traverseDOM(document.body);
},500);

<|endoftext|>