<commit_before>var chai = require('chai');
var expect = chai.expect;
var Clock = require('../../lib/Clock');
var Sequence = require('../../lib/Sequence');
var Note = require('../../lib/Note');
var Pattern = require('../../lib/Pattern');
var sinon = require('sinon');
var sinonChai = require("sinon-chai");
chai.use(sinonChai);

var clock;

describe('Clock', function () {

  beforeEach(function () {
    global.document = {};
    clock = new Clock();
  });

  afterEach(function () {
    clock.destroy();
  });

  describe('events', function () {
    var spy;
    beforeEach(function () {
      spy = sinon.spy();
      var MockedClock = Clock.extend({
        _scheduleSteps: spy
      });
      clock = new MockedClock();
    });
    describe('when change:bar is called', function () {
      it('should call _scheduleSteps()', function () {
        clock.trigger('change:bar');
        expect(spy).to.have.been.calledOnce;
      });
    });
    describe('when change:beat is called', function () {
      it('should call _scheduleSteps()', function () {
        clock.trigger('change:beat');
        expect(spy).to.have.been.calledOnce;
      });
    });
    describe('when change:tick is called', function () {
      it('should not call _scheduleSteps()', function () {
        clock.trigger('change:tick');
        expect(spy).not.to.have.been.called;
      });
    });
  });

  describe('step', function () {
    describe('when a clock.step function is defined', function () {
      describe('when it returns false', function () {
        it('should not schedule the note', function () {
          clock.step = function () { return false; };
          var pattern = clock.sequence = new Pattern();
          var note = new Note({ position: '1.1.01' });
          pattern.channel(1).add(note);
          var spy = note.start = sinon.spy();
          clock._queueNotesForStep('1.1.01', 10);
          expect(spy).not.to.have.been.called;
        });
      });
      describe('when it does not return false', function () {
        it('should schedule the note', function () {
          clock.step = function () { return; };
          var pattern = clock.sequence = new Pattern();
          var note = new Note({ position: '1.1.01' });
          pattern.channel(1).add(note);
          var spy = note.start = sinon.spy();
          clock._queueNotesForStep('1.1.01', 10);
          expect(spy).to.have.been.calledOnce;
        });
      });
    });
    describe('when a clock.step function is not defined', function () {
      it('should not throw an error', function () {
        expect(function () {
          var pattern = clock.sequence = new Pattern();
          var note = new Note({ position: '1.1.01' });
          pattern.channel(1).add(note);
          var spy = note.start = sinon.spy();
          clock._queueNotesForStep('1.1.01', 10);
          expect(spy).to.have.been.calledOnce;
        }).not.to.throw(Error);
      });
      it('should schedule the note', function () {
        var pattern = clock.sequence = new Pattern();
        var note = new Note({ position: '1.1.01' });
        pattern.channel(1).add(note);
        var spy = note.start = sinon.spy();
        clock._queueNotesForStep('1.1.01', 10);
        expect(spy).to.have.been.calledOnce;
      });
    });
  });

  describe('_canStartPlaying()', function () {
    describe('when document.readyState is "loading"', function () {
      it('should return false', function () {
        global.document.readyState = 'loading';
        expect(clock._canStartPlaying()).to.be.false;
      });
    });
    describe('when vent.loading is true', function () {
      it('should return false', function () {
        clock.vent.loading = true;
        expect(clock._canStartPlaying()).to.be.false;
      });
    });
    it('should return true', function () {
      expect(clock._canStartPlaying()).to.be.true;
    });
  });

  describe('start(sequence)', function () {
    describe('when _canStartPlaying() returns false', function () {
      it('should call start() again in ~10 ms', function (done) {
        clock._canStartPlaying = function () { return false; };
        clock.start();
        sinon.spy(clock, 'start');
        setTimeout(function () {
          expect(clock.start).to.have.been.called;
          done();
        }, 15);
      });
    });
    describe('when _canStartPlaying() returns true', function () {
      beforeEach(function () {
        clock._canStartPlaying = function () { return true; };
        clock.engine = {
          start: sinon.spy(),
          set: sinon.spy(),
          setBeatsPerBar: sinon.spy(),
          setLoopLength: sinon.spy(),
          setPosition: sinon.spy(),
          setTempo: sinon.spy()
        };
      });
      describe('when sequence is defined', function () {
        it('should set it as clock.sequence', function () {
          var sequence = new Sequence();
          clock.start(sequence);
          expect(clock.sequence).to.equal(sequence);
        });
      });
      describe('when sequence is not defined', function () {
        it('should not throw an error', function () {
          expect(function () {
            clock.start();
          }).not.to.throw(Error);
        });
      });
      it('it should not call engine.start immediately, but within 1ms', function (done) {
        clock.start();
        expect(clock.engine.start).not.to.have.been.called;
        setTimeout(function () {
          expect(clock.engine.start).to.have.been.called;
          done();
        }, 1);
      });
      describe('when restarting the sequence', function () {
        it('should set current position as _lastQueuedPosition', function () {
          clock.set('position', '1.3.54', { silent: true });
          clock.sequence = new Sequence();
          clock.start();
          expect(clock._lastQueuedPosition).to.equal('1.3.54');
        });
        it('should set current position as engine position', function () {
          clock.set('position', '1.3.54', { silent: true });
          clock.sequence = new Sequence();
          clock.start();
          expect(clock.engine.setPosition).to.have.been.called;
          expect(clock.engine.setPosition).to.have.been.calledWith('1.3.54');
        });
      });
      describe('when _stopByFold is true', function () {
        it('should set _stopByFold to false', function () {
          clock._stopByFold = true;
          clock.start();
          expect(clock._stopByFold).to.be.false
        });
        it('should set position to 1.1.01', function () {
          clock._stopByFold = true;
          clock.set('position', '2.4.96', { silent: true });
          clock.start();
          expect(clock.position).to.equal('1.1.01');
        });
      });
    });
  });

  describe('pause(sequence)', function () {
    beforeEach(function () {
      clock.set('playing', true, { silent: true });
    });
    it('should reset _lastQueuedPosition', function () {
      clock._lastQueuedPosition = '1.2.03';
      clock.pause();
      expect(clock._lastQueuedPosition).to.equal('0.0.00');
    });
    describe('when no sequence is defined', function () {
      it('should change playing state', function () {
        clock.sequence = new Pattern();
        clock.pause();
        expect(clock.playing).to.be.false;
      });
    });
    describe('when sequence is not clock.sequence', function () {
      it('should not change playing state', function () {
        clock.sequence = new Pattern();
        clock.pause(new Pattern());<commit_msg>fix clock tests sometimes missing a valid sequence<commit_after>var chai = require('chai');
var expect = chai.expect;
var Clock = require('../../lib/Clock');
var Sequence = require('../../lib/Sequence');
var Note = require('../../lib/Note');
var Pattern = require('../../lib/Pattern');
var sinon = require('sinon');
var sinonChai = require("sinon-chai");
chai.use(sinonChai);

var clock;

describe('Clock', function () {

  beforeEach(function () {
    global.document = {};
    clock = new Clock();
  });

  afterEach(function () {
    clock.destroy();
  });

  describe('events', function () {
    var spy;
    beforeEach(function () {
      spy = sinon.spy();
      var MockedClock = Clock.extend({
        _scheduleSteps: spy
      });
      clock = new MockedClock();
    });
    describe('when change:bar is called', function () {
      it('should call _scheduleSteps()', function () {
        clock.trigger('change:bar');
        expect(spy).to.have.been.calledOnce;
      });
    });
    describe('when change:beat is called', function () {
      it('should call _scheduleSteps()', function () {
        clock.trigger('change:beat');
        expect(spy).to.have.been.calledOnce;
      });
    });
    describe('when change:tick is called', function () {
      it('should not call _scheduleSteps()', function () {
        clock.trigger('change:tick');
        expect(spy).not.to.have.been.called;
      });
    });
  });

  describe('step', function () {
    describe('when a clock.step function is defined', function () {
      describe('when it returns false', function () {
        it('should not schedule the note', function () {
          clock.step = function () { return false; };
          var pattern = clock.sequence = new Pattern();
          var note = new Note({ position: '1.1.01' });
          pattern.channel(1).add(note);
          var spy = note.start = sinon.spy();
          clock._queueNotesForStep('1.1.01', 10);
          expect(spy).not.to.have.been.called;
        });
      });
      describe('when it does not return false', function () {
        it('should schedule the note', function () {
          clock.step = function () { return; };
          var pattern = clock.sequence = new Pattern();
          var note = new Note({ position: '1.1.01' });
          pattern.channel(1).add(note);
          var spy = note.start = sinon.spy();
          clock._queueNotesForStep('1.1.01', 10);
          expect(spy).to.have.been.calledOnce;
        });
      });
    });
    describe('when a clock.step function is not defined', function () {
      it('should not throw an error', function () {
        expect(function () {
          var pattern = clock.sequence = new Pattern();
          var note = new Note({ position: '1.1.01' });
          pattern.channel(1).add(note);
          var spy = note.start = sinon.spy();
          clock._queueNotesForStep('1.1.01', 10);
          expect(spy).to.have.been.calledOnce;
        }).not.to.throw(Error);
      });
      it('should schedule the note', function () {
        var pattern = clock.sequence = new Pattern();
        var note = new Note({ position: '1.1.01' });
        pattern.channel(1).add(note);
        var spy = note.start = sinon.spy();
        clock._queueNotesForStep('1.1.01', 10);
        expect(spy).to.have.been.calledOnce;
      });
    });
  });

  describe('_canStartPlaying()', function () {
    describe('when document.readyState is "loading"', function () {
      it('should return false', function () {
        global.document.readyState = 'loading';
        expect(clock._canStartPlaying()).to.be.false;
      });
    });
    describe('when vent.loading is true', function () {
      it('should return false', function () {
        clock.vent.loading = true;
        expect(clock._canStartPlaying()).to.be.false;
      });
    });
    it('should return true', function () {
      expect(clock._canStartPlaying()).to.be.true;
    });
  });

  describe('start(sequence)', function () {
    describe('when _canStartPlaying() returns false', function () {
      it('should call start() again in ~10 ms', function (done) {
        clock._canStartPlaying = function () { return false; };
        clock.sequence = new Pattern();
        clock.start();
        sinon.spy(clock, 'start');
        setTimeout(function () {
          expect(clock.start).to.have.been.called;
          done();
        }, 15);
      });
    });
    describe('when _canStartPlaying() returns true', function () {
      beforeEach(function () {
        clock.sequence = new Pattern();
        clock._canStartPlaying = function () { return true; };
        clock.engine = {
          start: sinon.spy(),
          set: sinon.spy(),
          setBeatsPerBar: sinon.spy(),
          setLoopLength: sinon.spy(),
          setPosition: sinon.spy(),
          setTempo: sinon.spy()
        };
      });
      describe('when sequence is defined', function () {
        it('should set it as clock.sequence', function () {
          var sequence = new Sequence();
          clock.start(sequence);
          expect(clock.sequence).to.equal(sequence);
        });
      });
      describe('when sequence is not defined', function () {
        it('should not throw an error', function () {
          expect(function () {
            clock.start();
          }).not.to.throw(Error);
        });
      });
      it('it should not call engine.start immediately, but within 1ms', function (done) {
        clock.sequence = new Pattern();
        clock.start();
        expect(clock.engine.start).not.to.have.been.called;
        setTimeout(function () {
          expect(clock.engine.start).to.have.been.called;
          done();
        }, 1);
      });
      describe('when restarting the sequence', function () {
        it('should set current position as _lastQueuedPosition', function () {
          clock.set('position', '1.3.54', { silent: true });
          clock.sequence = new Sequence();
          clock.start();
          expect(clock._lastQueuedPosition).to.equal('1.3.54');
        });
        it('should set current position as engine position', function () {
          clock.set('position', '1.3.54', { silent: true });
          clock.sequence = new Sequence();
          clock.start();
          expect(clock.engine.setPosition).to.have.been.called;
          expect(clock.engine.setPosition).to.have.been.calledWith('1.3.54');
        });
      });
      describe('when _stopByFold is true', function () {
        it('should set _stopByFold to false', function () {
          clock.sequence = new Pattern();
          clock._stopByFold = true;
          clock.start();
          expect(clock._stopByFold).to.be.false
        });
        it('should set position to 1.1.01', function () {
          clock.sequence = new Pattern();
          clock._stopByFold = true;
          clock.set('position', '2.4.96', { silent: true });
          clock.start();
          expect(clock.position).to.equal('1.1.01');
        });
      });
    });
  });

  describe('pause(sequence)', function () {
    beforeEach(function () {
      clock.set('playing', true, { silent: true });
    });
    it('should reset _lastQueuedPosition', function () {
      clock._lastQueuedPosition = '1.2.03';
      clock.pause();
      expect(clock._lastQueuedPosition).to.equal('0.0.00');
    });
    describe('when no sequence is defined', function () {
      it('should change playing state', function () {
        clock.sequence = new Pattern();
        clock.pause();
        expect(clock.playing).to.be.false;
      });
    });
    describe('when sequence is not clock.sequence', function () {
      it('should not change playing state', function () {
        clock.sequence = new Pattern();
        clock.pause(new Pattern());
{'fraction_non_alphanumeric': 0.1642824482330655, 'fraction_numerical': 0.011235221111764322, 'mean_word_length': 2.272066680914725, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1036161', 'n_tokens_mistral': 4443, 'n_tokens_neox': 4302, 'n_words': 955}