<commit_before>define(["helper/Basic", "Tone/event/Event", "Tone/core/Tone", "Tone/core/Transport", "helper/Offline2"],
	function (Basic, Event, Tone, Transport, Offline) {

	describe("Event", function(){

		Basic(Event);

		function resetTransport(done){
			Tone.Transport.cancel(0);
			Tone.Transport.off("start stop pause loop");
			Tone.Transport.stop();
			Tone.Transport.loop = false;
			Tone.Transport.bpm.value = 120;
			Tone.Transport.timeSignature = [4, 4];
			setTimeout(done, 200);
		}

		context("Constructor", function(){

			afterEach(resetTransport);

			it ("takes a callback and a value", function(){
				var callback = function(){};
				var note = new Event(callback, "C4");
				expect(note.callback).to.equal(callback);
				expect(note.value).to.equal("C4");
				note.dispose();
			});

			it ("can be constructed with no arguments", function(){
				var note = new Event();
				expect(note.value).to.be.null;
				note.dispose();
			});

			it ("can pass in arguments in options object", function(){
				var callback = function(){};
				var value = {"a" : 1};
				var note = new Event({
					"callback" : callback,
					"value" : value,
					"loop" : true,
					"loopEnd" : "4n",
					"probability" : 0.3
				});
				expect(note.callback).to.equal(callback);
				expect(note.value).to.equal(value);
				expect(note.loop).to.be.true;
				expect(note.loopEnd).to.equal("4n");
				expect(note.probability).to.equal(0.3);
				note.dispose();
			});
		});

		context("Get/Set", function(){

			afterEach(resetTransport);

			it ("can set values with object", function(){
				var callback = function(){};
				var note = new Event();
				note.set({
					"callback" : callback,
					"value" : "D4",
					"loop" : 8
				});
				expect(note.callback).to.equal(callback);
				expect(note.value).to.equal("D4");
				expect(note.loop).to.equal(8);
				note.dispose();
			});

			it ("can set get a the values as an object", function(){
				var callback = function(){};
				var note = new Event({
					"callback" : callback,
					"value" : "D3",
					"loop" : 4
				});
				var values = note.get();
				expect(values.value).to.equal("D3");
				expect(values.loop).to.equal(4);
				note.dispose();
			});
		});

		context("Event callback", function(){

			afterEach(resetTransport);

			it ("does not invoke get invoked until started", function(done){
				Offline(function(output, test, after){

					var note = new Event(function(){
						throw new Error("shouldn't call this callback");
					}, "C4");
					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});
				}, 0.3);
			});

			it ("is invoked after it's started", function(done){
				var note = new Event(function(){
					note.dispose();
					done();
				}, "C4").start(0);
				Tone.Transport.start();
			});

			it ("passes in the scheduled time to the callback", function(done){
				var now = Tone.Transport.now() + 0.1;
				var note = new Event(function(time){
					expect(time).to.be.a.number;
					expect(time - now).to.be.closeTo(0.3, 0.01);
					note.dispose();
					done();
				});
				note.start(0.3);
				Tone.Transport.start(now);
			});

			it ("passes in the value to the callback", function(done){
				var note = new Event(function(time, thing){
					expect(time).to.be.a.number;
					expect(thing).to.equal("thing");
					note.dispose();
					done();
				}, "thing").start();
				Tone.Transport.start();
			});

			it ("can mute the callback", function(done){
				Offline(function(output, test, after){
					var note = new Event(function(){
						throw new Error("shouldn't call this callback");
					}, "C4").start();

					note.mute = true;
					expect(note.mute).to.be.true;
					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});
				}, 0.3);
			});

			it ("can trigger with some probability", function(done){

				Offline(function(output, test, after){
					var note = new Event(function(){
						throw new Error("shouldn't call this callback");
					}, "C4").start();

					note.probability = 0;
					expect(note.probability).to.equal(0);
					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});
				}, 0.3);
			});
		});

		context("Scheduling", function(){

			afterEach(resetTransport);

			it ("can be started and stopped multiple times", function(done){
				Offline(function(output, test, after){
					var note = new Event().start(0).stop(0.2).start(0.4);

					Tone.Transport.start(0);

					test(function(sample, time){
						if (time > 0 && time < 0.18){
							expect(note.state).to.equal("started");
						} else if (time > 0.2 && time < 0.38){
							expect(note.state).to.equal("stopped");
						} else if (time > 0.4){
							expect(note.state).to.equal("started");
						}
					});

					after(function(){
						expect(note.state).to.equal("started");
						note.dispose();
						done();
					});
				}, 0.5);
			});

			it ("restarts when transport is restarted", function(done){

				Offline(function(output, test, after){
					var note = new Event().start(0).stop(0.4);

					Tone.Transport.start(0).stop(0.5).start(0.55);

					test(function(sample, time){
						if (time > 0 && time < 0.38){
							expect(note.state).to.equal("started");
						} else if (time > 0.4 && time < 0.5){
							expect(note.state).to.equal("stopped");
						} else if (time > 0.55 && time < 0.8){
							expect(note.state).to.equal("started");
						}
					});

					after(function(){
						expect(Tone.Transport.state).to.equal("started");
						expect(note.state).to.equal("stopped");
						note.dispose();
						done();
					});
				}, 1);
			});

			it ("can be cancelled", function(done){
				var note = new Event().start(0);
				setTimeout(function(){
					expect(note.state).to.equal("started");
					Tone.Transport.stop();
					note.cancel();
					setTimeout(function(){
						Tone.Transport.start();
						setTimeout(function(){
							expect(note.state).to.equal("stopped");
							note.dispose();
							done();
						}, 100);
					}, 100);
				}, 100);
				Tone.Transport.start();
			});

		});

		context("Looping", function(){

			afterEach(resetTransport);

			it ("can be set to loop", function(done){

				Offline(function(output, test, after){

					var callCount = 0;

					var note = new Event({
						"loopEnd" : 0.25,
						"loop" : true,
						"callback" : function(){
							callCount++;
						}
					}).start(0);

					Tone.Transport.start(0);

					after(function(){
						expect(callCount).to.equal(4);
						note.dispose();
						done();
					});
				}, 0.8);

			});

			it ("can be set to loop at a specific interval", function(done){
				Offline(function(output, test, after){
					var lastCall;
					var note = new Event({
						"loopEnd" : 0.25,
						"loop" : true,
						"callback" : function(time){
							if (lastCall){
								expect(time - lastCall).to.be.closeTo(0.25, 0.01);
							}
							lastCall = time;
						}
					}).start(0);
					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});

				}, 1);
			});

			it ("can adjust the loop duration after starting", function(done){

				Offline(function(output, test, after){

					var lastCall;

					var note = new Event({
						"loopEnd" : 0.5,
						"loop" : true,
						"callback" : function(time){
							if (lastCall){
								expect(time - lastCall).to.be.closeTo(0.25, 0.01);
							} else {
								note.loopEnd = 0.25;
							}
							lastCall = time;
						}
					}).start(0);

					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});
				}, 0.8);
			});

			it ("can loop a specific number of times", function(done){

				Offline(function(output, test, after){

					var callCount = 0;

					var note = new Event({
						"loopEnd" : 0.125,
						"loop" : 3,
						"callback" : function(){
							callCount++;
						}
					}).start(0);

					Tone.Transport.start();

					after(function(){
						expect(callCount).to.equal(3);
						note.dispose();
						done();
					});
				}, 0.8);
			});

			it ("can be started and stopped multiple times", function(done){

				Offline(function(output, test, after){

					var eventTimes = [0.3, 0.4, 0.9, 1.0, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9];
					var eventTimeIndex = 0;

					var note = new Event({
						"loopEnd" : 0.1,
						"loop" : true,
						"callback" : function(time){
							expect(eventTimes.length).to.be.gt(eventTimeIndex);
							expect(eventTimes[eventTimeIndex]).to.be.closeTo(time, 0.05);
							eventTimeIndex++;
						}
					}).start(0.1).stop(0.2).start(0.5).stop(1.1);

					Tone.Transport.start(0.2).stop(0.5).start(0.8);

					after(function(){
						note.dispose();
						done();
					});
				}, 2);
			});

			it ("loops the correct amount of times when the event is started in the Transport's past", function(done){

				Offline(function(output, test, after){

					var callCount = 0;
					var note = new Event({
						"loopEnd" : 0.2,
						"loop" : 3,
						"callback" : function(){
							callCount++;
						}
					});

					Tone.Transport.start();

					var wasCalled = false;

					test(function(sample, time){

						if (time > 0.1 && !wasCalled) {
							wasCalled = true;
							note.start(0);
						}
					});

					after(function(){
						expect(callCount).to.equal(2);
						note.dispose();
						done();
					});

				}, 0.7);
			});

			it ("reports the progress of the loop", function(done){

				Offline(function(output, test, after){

					var note = new Event({
						"loopEnd" : 1,
						"loop" : true,
					}).start(0);

					Tone.Transport.start();

					after(function(){
						expect(note.progress).to.be.closeTo(0.8, 0.05);
						note.dispose();
						done();
					});
				}, 0.8);
			});

			it ("progress is 0 when not looping", function(done){
				Offline(function(output, test, after){

					var note = new Event({
						"loopEnd" : 0.25,
						"loop" : false,
					}).start(0);

					Tone.Transport.start();

					after(function(){
						expect(note.progress).to.equal(0);
						note.dispose();
						done();
					});
				}, 0.8);
			});
		});

		context("playbackRate and humanize", function(){

			afterEach(resetTransport);

			it ("can adjust the playbackRate", function(done){

				Offline(function(output, test, after){

					var lastCall;
					var note = new Event({
						"playbackRate" : 2,
						"loopEnd" : 0.5,
						"loop" : true,
						"callback" : function(time){
							if (lastCall){
								expect(time - lastCall).to.be.closeTo(0.25, 0.01);
							}
							lastCall = time;
						}
					}).start(0);

					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});

				}, 0.7);
			});

			it ("can adjust the playbackRate after starting", function(done){

				Offline(function(output, test, after){
					var lastCall;
					var note = new Event({
						"playbackRate" : 1,
						"loopEnd" : 0.25,
						"loop" : true,
						"callback" : function(time){
							if (lastCall){
								expect(time - lastCall).to.be.closeTo(0.5, 0.01);
							} else {
								note.playbackRate = 0.5;
							}
							lastCall = time;
						}
					}).start(0);
					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});
				}, 1.2);

			});

			it ("can humanize the callback by some amount", function(done){

				Offline(function(output, test, after){

					var lastCall;

					var note = new Event({
						"humanize" : 0.05,
						"loopEnd" : 0.25,
						"loop" : true,
						"callback" : function(time){
							if (lastCall){
								expect(time - lastCall).to.be.within(0.2, 0.3);
							}
							lastCall += 0.25;
						}
					}).start(0);

					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});

				}, 0.6);
			});

		});

	});
});<commit_msg>narrowing threshold of test<commit_after>define(["helper/Basic", "Tone/event/Event", "Tone/core/Tone", "Tone/core/Transport", "helper/Offline2"],
	function (Basic, Event, Tone, Transport, Offline) {

	describe("Event", function(){

		Basic(Event);

		function resetTransport(done){
			Tone.Transport.cancel(0);
			Tone.Transport.off("start stop pause loop");
			Tone.Transport.stop();
			Tone.Transport.loop = false;
			Tone.Transport.bpm.value = 120;
			Tone.Transport.timeSignature = [4, 4];
			setTimeout(done, 200);
		}

		context("Constructor", function(){

			afterEach(resetTransport);

			it ("takes a callback and a value", function(){
				var callback = function(){};
				var note = new Event(callback, "C4");
				expect(note.callback).to.equal(callback);
				expect(note.value).to.equal("C4");
				note.dispose();
			});

			it ("can be constructed with no arguments", function(){
				var note = new Event();
				expect(note.value).to.be.null;
				note.dispose();
			});

			it ("can pass in arguments in options object", function(){
				var callback = function(){};
				var value = {"a" : 1};
				var note = new Event({
					"callback" : callback,
					"value" : value,
					"loop" : true,
					"loopEnd" : "4n",
					"probability" : 0.3
				});
				expect(note.callback).to.equal(callback);
				expect(note.value).to.equal(value);
				expect(note.loop).to.be.true;
				expect(note.loopEnd).to.equal("4n");
				expect(note.probability).to.equal(0.3);
				note.dispose();
			});
		});

		context("Get/Set", function(){

			afterEach(resetTransport);

			it ("can set values with object", function(){
				var callback = function(){};
				var note = new Event();
				note.set({
					"callback" : callback,
					"value" : "D4",
					"loop" : 8
				});
				expect(note.callback).to.equal(callback);
				expect(note.value).to.equal("D4");
				expect(note.loop).to.equal(8);
				note.dispose();
			});

			it ("can set get a the values as an object", function(){
				var callback = function(){};
				var note = new Event({
					"callback" : callback,
					"value" : "D3",
					"loop" : 4
				});
				var values = note.get();
				expect(values.value).to.equal("D3");
				expect(values.loop).to.equal(4);
				note.dispose();
			});
		});

		context("Event callback", function(){

			afterEach(resetTransport);

			it ("does not invoke get invoked until started", function(done){
				Offline(function(output, test, after){

					var note = new Event(function(){
						throw new Error("shouldn't call this callback");
					}, "C4");
					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});
				}, 0.3);
			});

			it ("is invoked after it's started", function(done){
				var note = new Event(function(){
					note.dispose();
					done();
				}, "C4").start(0);
				Tone.Transport.start();
			});

			it ("passes in the scheduled time to the callback", function(done){
				var now = Tone.Transport.now() + 0.1;
				var note = new Event(function(time){
					expect(time).to.be.a.number;
					expect(time - now).to.be.closeTo(0.3, 0.01);
					note.dispose();
					done();
				});
				note.start(0.3);
				Tone.Transport.start(now);
			});

			it ("passes in the value to the callback", function(done){
				var note = new Event(function(time, thing){
					expect(time).to.be.a.number;
					expect(thing).to.equal("thing");
					note.dispose();
					done();
				}, "thing").start();
				Tone.Transport.start();
			});

			it ("can mute the callback", function(done){
				Offline(function(output, test, after){
					var note = new Event(function(){
						throw new Error("shouldn't call this callback");
					}, "C4").start();

					note.mute = true;
					expect(note.mute).to.be.true;
					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});
				}, 0.3);
			});

			it ("can trigger with some probability", function(done){

				Offline(function(output, test, after){
					var note = new Event(function(){
						throw new Error("shouldn't call this callback");
					}, "C4").start();

					note.probability = 0;
					expect(note.probability).to.equal(0);
					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});
				}, 0.3);
			});
		});

		context("Scheduling", function(){

			afterEach(resetTransport);

			it ("can be started and stopped multiple times", function(done){
				Offline(function(output, test, after){
					var note = new Event().start(0).stop(0.2).start(0.4);

					Tone.Transport.start(0);

					test(function(sample, time){
						if (time > 0 && time < 0.18){
							expect(note.state).to.equal("started");
						} else if (time > 0.2 && time < 0.38){
							expect(note.state).to.equal("stopped");
						} else if (time > 0.4){
							expect(note.state).to.equal("started");
						}
					});

					after(function(){
						expect(note.state).to.equal("started");
						note.dispose();
						done();
					});
				}, 0.5);
			});

			it ("restarts when transport is restarted", function(done){

				Offline(function(output, test, after){
					var note = new Event().start(0).stop(0.4);

					Tone.Transport.start(0).stop(0.5).start(0.55);

					test(function(sample, time){
						if (time > 0 && time < 0.38){
							expect(note.state).to.equal("started");
						} else if (time > 0.4 && time < 0.5){
							expect(note.state).to.equal("stopped");
						} else if (time > 0.55 && time < 0.8){
							expect(note.state).to.equal("started");
						}
					});

					after(function(){
						expect(Tone.Transport.state).to.equal("started");
						expect(note.state).to.equal("stopped");
						note.dispose();
						done();
					});
				}, 1);
			});

			it ("can be cancelled", function(done){
				var note = new Event().start(0);
				setTimeout(function(){
					expect(note.state).to.equal("started");
					Tone.Transport.stop();
					note.cancel();
					setTimeout(function(){
						Tone.Transport.start();
						setTimeout(function(){
							expect(note.state).to.equal("stopped");
							note.dispose();
							done();
						}, 100);
					}, 100);
				}, 100);
				Tone.Transport.start();
			});

		});

		context("Looping", function(){

			afterEach(resetTransport);

			it ("can be set to loop", function(done){

				Offline(function(output, test, after){

					var callCount = 0;

					var note = new Event({
						"loopEnd" : 0.25,
						"loop" : true,
						"callback" : function(){
							callCount++;
						}
					}).start(0);

					Tone.Transport.start(0);

					after(function(){
						expect(callCount).to.equal(4);
						note.dispose();
						done();
					});
				}, 0.8);

			});

			it ("can be set to loop at a specific interval", function(done){
				Offline(function(output, test, after){
					var lastCall;
					var note = new Event({
						"loopEnd" : 0.25,
						"loop" : true,
						"callback" : function(time){
							if (lastCall){
								expect(time - lastCall).to.be.closeTo(0.25, 0.01);
							}
							lastCall = time;
						}
					}).start(0);
					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});

				}, 1);
			});

			it ("can adjust the loop duration after starting", function(done){

				Offline(function(output, test, after){

					var lastCall;

					var note = new Event({
						"loopEnd" : 0.5,
						"loop" : true,
						"callback" : function(time){
							if (lastCall){
								expect(time - lastCall).to.be.closeTo(0.25, 0.01);
							} else {
								note.loopEnd = 0.25;
							}
							lastCall = time;
						}
					}).start(0);

					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});
				}, 0.8);
			});

			it ("can loop a specific number of times", function(done){

				Offline(function(output, test, after){

					var callCount = 0;

					var note = new Event({
						"loopEnd" : 0.125,
						"loop" : 3,
						"callback" : function(){
							callCount++;
						}
					}).start(0);

					Tone.Transport.start();

					after(function(){
						expect(callCount).to.equal(3);
						note.dispose();
						done();
					});
				}, 0.8);
			});

			it ("can be started and stopped multiple times", function(done){

				Offline(function(output, test, after){

					var eventTimes = [0.3, 0.4, 0.9, 1.0, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9];
					var eventTimeIndex = 0;

					var note = new Event({
						"loopEnd" : 0.1,
						"loop" : true,
						"callback" : function(time){
							expect(eventTimes.length).to.be.gt(eventTimeIndex);
							expect(eventTimes[eventTimeIndex]).to.be.closeTo(time, 0.05);
							eventTimeIndex++;
						}
					}).start(0.1).stop(0.2).start(0.5).stop(1.1);

					Tone.Transport.start(0.2).stop(0.5).start(0.8);

					after(function(){
						note.dispose();
						done();
					});
				}, 2);
			});

			it ("loops the correct amount of times when the event is started in the Transport's past", function(done){

				Offline(function(output, test, after){

					var callCount = 0;
					var note = new Event({
						"loopEnd" : 0.2,
						"loop" : 3,
						"callback" : function(){
							callCount++;
						}
					});

					Tone.Transport.start();

					var wasCalled = false;

					test(function(sample, time){

						if (time > 0.1 && !wasCalled) {
							wasCalled = true;
							note.start(0);
						}
					});

					after(function(){
						expect(callCount).to.equal(2);
						note.dispose();
						done();
					});

				}, 1);
			});

			it ("reports the progress of the loop", function(done){

				Offline(function(output, test, after){

					var note = new Event({
						"loopEnd" : 1,
						"loop" : true,
					}).start(0);

					Tone.Transport.start();

					after(function(){
						expect(note.progress).to.be.closeTo(0.8, 0.1);
						note.dispose();
						done();
					});
				}, 0.8);
			});

			it ("progress is 0 when not looping", function(done){
				Offline(function(output, test, after){

					var note = new Event({
						"loopEnd" : 0.25,
						"loop" : false,
					}).start(0);

					Tone.Transport.start();

					after(function(){
						expect(note.progress).to.equal(0);
						note.dispose();
						done();
					});
				}, 0.8);
			});
		});

		context("playbackRate and humanize", function(){

			afterEach(resetTransport);

			it ("can adjust the playbackRate", function(done){

				Offline(function(output, test, after){

					var lastCall;
					var note = new Event({
						"playbackRate" : 2,
						"loopEnd" : 0.5,
						"loop" : true,
						"callback" : function(time){
							if (lastCall){
								expect(time - lastCall).to.be.closeTo(0.25, 0.01);
							}
							lastCall = time;
						}
					}).start(0);

					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});

				}, 0.7);
			});

			it ("can adjust the playbackRate after starting", function(done){

				Offline(function(output, test, after){
					var lastCall;
					var note = new Event({
						"playbackRate" : 1,
						"loopEnd" : 0.25,
						"loop" : true,
						"callback" : function(time){
							if (lastCall){
								expect(time - lastCall).to.be.closeTo(0.5, 0.01);
							} else {
								note.playbackRate = 0.5;
							}
							lastCall = time;
						}
					}).start(0);
					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});
				}, 1.2);

			});

			it ("can humanize the callback by some amount", function(done){

				Offline(function(output, test, after){

					var lastCall;

					var note = new Event({
						"humanize" : 0.05,
						"loopEnd" : 0.25,
						"loop" : true,
						"callback" : function(time){
							if (lastCall){
								expect(time - lastCall).to.be.within(0.2, 0.3);
							}
							lastCall += 0.25;
						}
					}).start(0);

					Tone.Transport.start();

					after(function(){
						note.dispose();
						done();
					});

				}, 0.6);
			});

		});

	});
});<|endoftext|>


<commit_before>'use strict';
var assert = require('chai').assert;
var fs = require('fs');
var path = require('path');
var fixture = path.resolve.bind(path, __dirname, 'fixtures');

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

describe('Librarian', function(){

    var NOOP = function(){};

    it('should expose constructor', function(){
        assert.isFunction(Librarian);
    });

    it('should not require new keyword', function(){
        var l = Librarian();
        assert.instanceOf(l, Librarian);
    });

    it('should have a DEFAULTS object', function(){
        assert.isObject(Librarian.DEFAULTS);
    });

    it('should take an options object', function(){
        var options = {directory:'my-directory'};
        var l = Librarian(options);
        assert.ok(l.directory(), 'my-directory');
    });

    it('should take a single string argument that will be the working directory', function(){
        //this might change!
        var l = Librarian('my-directory');
        assert.ok(l.directory(), 'my-directory');
    });

    xdescribe('#use', function(){
        it('should add plugin to stack', function(){
            var l = Librarian();
            l.use(NOOP);
            assert.equal(l.plugins.length, 1);
        });
    });

    describe('#directory', function(){

        it('should set a working directory by default equal to process.env.PWD', function(){
            var l = Librarian();
            assert.equal(l.directory(), process.env.PWD);
        });

        it('should set the working directory', function(){
            var l = Librarian({directory:'dir'});
            assert.ok(l.directory(), 'dir');
        });

        it('should respect absolute directories', function(){
            var l = Librarian({directory:'/dir'});
            assert.ok(l.directory(), '/dir');
        });
    });

    describe('#source', function(){
        it('should set a "source" directory in DEFAULTS', function(){
            var l = Librarian();
            assert.ok(l.source(), Librarian.DEFAULTS.source);
        });

        it('should set the "source" directory', function(){
            var l = Librarian({source:'dir'});
            assert.ok(l.directory(), 'dir');
        });

        it('should get full path of source directory', function(){
            var l = Librarian();
            var absoluteBuildPath = path.join(process.env.PWD, '/build');
            assert.ok(l.source(), absoluteBuildPath);
        });

        it('should respect absolute directories', function(){
            var l = Librarian({source:'/dir'});
            assert.ok(l.source(), '/dir');
        });

        it('should throw on non strings', function(){
            var l = Librarian();
            assert.throws(function(){
                l.source(23);
            });
        });
    });

    describe('#destination', function(){
        it('should set a destination directory in DEFAULTS', function(){
            var l = Librarian();
            assert.ok(l.destination(), Librarian.DEFAULTS.destination);
        });

        it('should get full path of destination directory', function(){
            var l = Librarian();
            var absoluteBuildPath = path.join(process.env.PWD, '/build');
            assert.ok(l.destination(), absoluteBuildPath);
        });

        it('should respect absolute directories', function(){
            var l = Librarian({destination:'/dir'});
            assert.ok(l.destination(), '/dir');
        });

        it('should throw on non strings', function(){
            var l = Librarian();
            assert.throws(function(){
                l.destination(23);
            });
        });
    });

    describe('#clean', function(){
        it('should set the "clean" default used in DEFAULTS', function(){
            var l = Librarian();
            assert.equal(l.clean(), Librarian.DEFAULTS.clean);
        });

        it('should set the "clean" option', function(){
            var l = Librarian();
            l.clean(false);
            assert.equal(l.clean(), false);
        });

        it('should throw on on boolean', function(){
            var l = Librarian();
            assert.throws(function(){
                l.clean(23);
            });
        });
    });

    describe('#frontmatter', function(){
        it('should set the "frontmatter" default used in DEFAULTS', function(){
            var l = Librarian();
            assert.equal(l.frontmatter(), Librarian.DEFAULTS.frontmatter);
        });

        it('should initialize the "frontmatter" option', function(){
            var l = Librarian({frontmatter: true});
            assert.equal(l.frontmatter(), true)
        });

        it('should set the "frontmatter"', function(){
            var l = Librarian();
            l.frontmatter(true);
            assert.equal(l.frontmatter(), true)
        });

        it('should throw on on boolean', function(){
            var l = Librarian();
            assert.throws(function(){
                l.frontmatter(23);
            });
        });
    });

    describe('#metadata', function(){
        it('should set the "metadata" default used in DEFAULTS', function(){
            var l = Librarian();
            assert.deepEqual(l.metadata(), Librarian.DEFAULTS.metadata);
        });

        it('should initialize the "metadata" option', function(){
            var meta = {
                user: 'goliatone',
                url:'http://goliatone.com'
            };

            var l = Librarian({metadata: meta});
            assert.deepEqual(l.metadata(), meta);
        });

        it('should get "metadata"', function(){
            var l = Librarian();
            assert.deepEqual(l.metadata(), {});
        });

        it('should set "metadata" clone', function(){
            var meta = {
                user: 'goliatone',
                url:'http://goliatone.com'
            };
            var l = Librarian();
            l.metadata(meta);
            assert.notEqual(l.metadata(), meta);
            assert.deepEqual(l.metadata(), meta);
        });
    });

    describe('#attributes', function(){
        it('should set the "attributes" default used in DEFAULTS', function(){
            var l = Librarian();
            assert.deepEqual(l._attributes, Librarian.DEFAULTS.attributes);
        });

        it('should initialize the "attributes" option', function(){
            var attributes = ['stats', 'content'];
            var l = Librarian({attributes: attributes});
            assert.ok(l.attributes(), attributes);
        });

        it('should get "attributes" option', function(){
            var l = Librarian();
            assert.deepEqual(l.attributes(), Librarian.DEFAULTS.attributes);
        });

        it('should set "attributes" option', function(){
            var l = Librarian();
            var attributes = ['stats', 'content'];
            l.attributes(attributes);
            assert.ok(l.attributes(), attributes);
        });
    });

    describe('#path', function(){
        it('should return a path relative to the working directory', function(){
            var l = Librarian({source:'test/tmp'});
            var rel = l.path('one', 'two', 'three');
            assert.ok(rel, '/test/tmp/one/two/three');
        });
    });

    describe('#read', function(){
        it('should read from a source directory', function(done){
            var l = Librarian({
                directory: fixture('read')
            });
            var stats = fs.statSync(fixture('read/src/index.md'));

            l.read(function(err, files){
                if(err) return done(err);
                assert.ok(files, {
                    'index.md': {
                        title: 'A Title',
                        contents: new Buffer('body'),
                        mode: stats.mode.toString(8).slice(-4),
                        stats:stats,
                        isUtf8: true
                    }
                });
                done();
            });
        });

        it('should read from a provided directory', function(done){
            var l = Librarian({
                directory: fixture('read-dir')
            });
            var stats = fs.statSync(fixture('read-dir/dir/index.md'));
            var dir = fixture('read-dir/dir');
            l.read(dir, function(err, files){
                if(err) done(err);
                assert.ok(files, {
                    'index.md': {
                        title: 'A Title',
                        contents: new Buffer('body'),
                        mode: stats.mode.toString(8).slice(-4),
                        stats:stats,
                        isUtf8: true
                    }
                });
            });
            done();
        });

        it('should preserve an existing file mode', function(done){
            var l = Librarian({
                directory: fixture('read-mode')
            });
            var stats = fs.statSync(fixture('read-mode/src/bin'));

            l.read(function(err, files){
                if(err) done(err);
                assert.ok(files, {
                    'bin': {
                        contents: new Buffer('echo test'),
                        mode: stats.mode.toString(8).slice(-4),
                        stats: stats,
                        isUtf8: false
                    }
                });
            });
            done();
        });

        describe('should expose isUtf8 metadata property', function(){
            it('should be false for binary files', function(done){
                var l = Librarian({
                    directory: fixture('read-isUtf8-false')
                });

                l.read(function(err, files){
                    if(err) done(err);
                    assert.isFalse(files['image.png'].isUtf8);
                });
                done();
            });

            it('should be true for text files', function(done){
                var l = Librarian({
                    directory: fixture('read-isUtf8-true')
                });

                l.read(function(err, files){
                    if(err) done(err);
                    assert.isTrue(files['index.md'].isUtf8);
                });
                done();
            });
        });

        it('should expose attributes in each file metadata', function(done){
            var l = Librarian({
                directory: fixture('expose-attributes')
            });
            l.read(function(err, files){
                if(err) done(err);
                var file = files['index.md'];
                Librarian.DEFAULTS.attributes.map(function(attr){
                    assert.property(file, attr, attr);
                });
            });
            done();
        });

        it('should not parse front-matter if "frontmatter" is false', function(done){
            var l = Librarian({
                directory: fixture('read-frontmatter'),
                frontmatter: false
            });
            l.read(function(err, files){
                if(err) done(err);
                assert.isUndefined(files['index.md'].title);
            });
            done();
        });
    });
});<commit_msg>TESTS: wip<commit_after>'use strict';
var assert = require('chai').assert;
var fs = require('fs');
var path = require('path');
var equal = require('assert-dir-equal');
var fixture = path.resolve.bind(path, __dirname, 'fixtures');

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

describe('Librarian', function(){

    var NOOP = function(){};

    it('should expose constructor', function(){
        assert.isFunction(Librarian);
    });

    it('should not require new keyword', function(){
        var l = Librarian();
        assert.instanceOf(l, Librarian);
    });

    it('should have a DEFAULTS object', function(){
        assert.isObject(Librarian.DEFAULTS);
    });

    it('should take an options object', function(){
        var options = {directory:'my-directory'};
        var l = Librarian(options);
        assert.ok(l.directory(), 'my-directory');
    });

    it('should take a single string argument that will be the working directory', function(){
        //this might change!
        var l = Librarian('my-directory');
        assert.ok(l.directory(), 'my-directory');
    });

    xdescribe('#use', function(){
        it('should add plugin to stack', function(){
            var l = Librarian();
            l.use(NOOP);
            assert.equal(l.plugins.length, 1);
        });
    });

    describe('#directory', function(){

        it('should set a working directory by default equal to process.env.PWD', function(){
            var l = Librarian();
            assert.equal(l.directory(), process.env.PWD);
        });

        it('should set the working directory', function(){
            var l = Librarian({directory:'dir'});
            assert.ok(l.directory(), 'dir');
        });

        it('should respect absolute directories', function(){
            var l = Librarian({directory:'/dir'});
            assert.ok(l.directory(), '/dir');
        });
    });

    describe('#source', function(){
        it('should set a "source" directory in DEFAULTS', function(){
            var l = Librarian();
            assert.ok(l.source(), Librarian.DEFAULTS.source);
        });

        it('should set the "source" directory', function(){
            var l = Librarian({source:'dir'});
            assert.ok(l.directory(), 'dir');
        });

        it('should get full path of source directory', function(){
            var l = Librarian();
            var absoluteBuildPath = path.join(process.env.PWD, '/build');
            assert.ok(l.source(), absoluteBuildPath);
        });

        it('should respect absolute directories', function(){
            var l = Librarian({source:'/dir'});
            assert.ok(l.source(), '/dir');
        });

        it('should throw on non strings', function(){
            var l = Librarian();
            assert.throws(function(){
                l.source(23);
            });
        });
    });

    describe('#destination', function(){
        it('should set a destination directory in DEFAULTS', function(){
            var l = Librarian();
            assert.ok(l.destination(), Librarian.DEFAULTS.destination);
        });

        it('should get full path of destination directory', function(){
            var l = Librarian();
            var absoluteBuildPath = path.join(process.env.PWD, '/build');
            assert.ok(l.destination(), absoluteBuildPath);
        });

        it('should respect absolute directories', function(){
            var l = Librarian({destination:'/dir'});
            assert.ok(l.destination(), '/dir');
        });

        it('should throw on non strings', function(){
            var l = Librarian();
            assert.throws(function(){
                l.destination(23);
            });
        });
    });

    describe('#clean', function(){
        it('should set the "clean" default used in DEFAULTS', function(){
            var l = Librarian();
            assert.equal(l.clean(), Librarian.DEFAULTS.clean);
        });

        it('should set the "clean" option', function(){
            var l = Librarian();
            l.clean(false);
            assert.equal(l.clean(), false);
        });

        it('should throw on on boolean', function(){
            var l = Librarian();
            assert.throws(function(){
                l.clean(23);
            });
        });
    });

    describe('#frontmatter', function(){
        it('should set the "frontmatter" default used in DEFAULTS', function(){
            var l = Librarian();
            assert.equal(l.frontmatter(), Librarian.DEFAULTS.frontmatter);
        });

        it('should initialize the "frontmatter" option', function(){
            var l = Librarian({frontmatter: true});
            assert.equal(l.frontmatter(), true)
        });

        it('should set the "frontmatter"', function(){
            var l = Librarian();
            l.frontmatter(true);
            assert.equal(l.frontmatter(), true)
        });

        it('should throw on on boolean', function(){
            var l = Librarian();
            assert.throws(function(){
                l.frontmatter(23);
            });
        });
    });

    describe('#metadata', function(){
        it('should set the "metadata" default used in DEFAULTS', function(){
            var l = Librarian();
            assert.deepEqual(l.metadata(), Librarian.DEFAULTS.metadata);
        });

        it('should initialize the "metadata" option', function(){
            var meta = {
                user: 'goliatone',
                url:'http://goliatone.com'
            };

            var l = Librarian({metadata: meta});
            assert.deepEqual(l.metadata(), meta);
        });

        it('should get "metadata"', function(){
            var l = Librarian();
            assert.deepEqual(l.metadata(), {});
        });

        it('should set "metadata" clone', function(){
            var meta = {
                user: 'goliatone',
                url:'http://goliatone.com'
            };
            var l = Librarian();
            l.metadata(meta);
            assert.notEqual(l.metadata(), meta);
            assert.deepEqual(l.metadata(), meta);
        });
    });

    describe('#attributes', function(){
        it('should set the "attributes" default used in DEFAULTS', function(){
            var l = Librarian();
            assert.deepEqual(l._attributes, Librarian.DEFAULTS.attributes);
        });

        it('should initialize the "attributes" option', function(){
            var attributes = ['stats', 'content'];
            var l = Librarian({attributes: attributes});
            assert.ok(l.attributes(), attributes);
        });

        it('should get "attributes" option', function(){
            var l = Librarian();
            assert.deepEqual(l.attributes(), Librarian.DEFAULTS.attributes);
        });

        it('should set "attributes" option', function(){
            var l = Librarian();
            var attributes = ['stats', 'content'];
            l.attributes(attributes);
            assert.ok(l.attributes(), attributes);
        });
    });

    describe('#path', function(){
        it('should return a path relative to the working directory', function(){
            var l = Librarian({source:'test/tmp'});
            var rel = l.path('one', 'two', 'three');
            assert.ok(rel, '/test/tmp/one/two/three');
        });
    });

    describe('#read', function(){
        it('should read from a source directory', function(done){
            var l = Librarian({
                directory: fixture('read')
            });
            var stats = fs.statSync(fixture('read/src/index.md'));

            l.read(function(err, files){
                if(err) return done(err);
                assert.ok(files, {
                    'index.md': {
                        title: 'A Title',
                        contents: new Buffer('body'),
                        mode: stats.mode.toString(8).slice(-4),
                        stats:stats,
                        isUtf8: true
                    }
                });
                done();
            });
        });

        it('should read from a provided directory', function(done){
            var l = Librarian({
                directory: fixture('read-dir')
            });
            var stats = fs.statSync(fixture('read-dir/dir/index.md'));
            var dir = fixture('read-dir/dir');
            l.read(dir, function(err, files){
                if(err) done(err);
                assert.ok(files, {
                    'index.md': {
                        title: 'A Title',
                        contents: new Buffer('body'),
                        mode: stats.mode.toString(8).slice(-4),
                        stats:stats,
                        isUtf8: true
                    }
                });
            });
            done();
        });

        it('should preserve an existing file mode', function(done){
            var l = Librarian({
                directory: fixture('read-mode')
            });
            var stats = fs.statSync(fixture('read-mode/src/bin'));

            l.read(function(err, files){
                if(err) done(err);
                assert.ok(files, {
                    'bin': {
                        contents: new Buffer('echo test'),
                        mode: stats.mode.toString(8).slice(-4),
                        stats: stats,
                        isUtf8: false
                    }
                });
            });
            done();
        });

        describe('should expose isUtf8 "metadata" property', function(){
            it('should be false for binary files', function(done){
                var l = Librarian({
                    directory: fixture('read-isUtf8-false')
                });

                l.read(function(err, files){
                    if(err) done(err);
                    assert.isFalse(files['image.png'].isUtf8);
                });
                done();
            });

            it('should be true for text files', function(done){
                var l = Librarian({
                    directory: fixture('read-isUtf8-true')
                });

                l.read(function(err, files){
                    if(err) done(err);
                    assert.isTrue(files['index.md'].isUtf8);
                });
                done();
            });
        });

        it('should expose attributes in each file "metadata"', function(done){
            var l = Librarian({
                directory: fixture('expose-attributes')
            });
            l.read(function(err, files){
                if(err) done(err);
                var file = files['index.md'];
                Librarian.DEFAULTS.attributes.map(function(attr){
                    assert.property(file, attr, attr);
                });
            });
            done();
        });

        it('should not parse front-matter if "frontmatter" is false', function(done){
            var l = Librarian({
                directory: fixture('read-frontmatter'),
                frontmatter: false
            });
            l.read(function(err, files){
                if(err) done(err);
                assert.isUndefined(files['index.md'].title);
            });
            done();
        });
    });

    describe('#write', function(){
        it('should write to a destination directory', function(done){
            var l = Librarian({
                directory: fixture('write')
            });
            var files = {'index.md':{contents: new Buffer('body')}};
            l.write(files, function(err){
                if(err) return done(err);
                equal(fixture('write/build'), fixture('write/expected'));
                done();
            });
        });

        it('should write to a provided directory', function(done){
            var l = Librarian({
                directory: fixture('write-dir')
            });
            var files = {'index.md':{contents: new Buffer('body')}};
            var dir = fixture('write-dir/out');
            l.write(files, dir, function(err){
                if(err) return done(err);
                equal(fixture('write-dir/out'), fixture('write-dir/expected'));
                done();
            });
        });
    });
});<|endoftext|>


<commit_before>class LinearSystem {
  constructor(matrix) {
    //input should be a array of array of ints
    if ( ! Array.isArray(matrix)) {
      throw 'not array type error';
    }
    const hight = matrix.length;
    matrix.forEach(function(row){
      if ( ! Array.isArray(row)) {
        throw 'not array type error';
      }
      //checks if input matrix is ( column.length + 1 == rows.length )
      if ( hight + 1 != row.length ) {
        throw 'not in required shape (width == hight + 1)';
      }
      row.forEach(function(entry){
        if ( ! Number.isInteger(entry)) {
          throw 'not a integer error';
        }
      });
    });
    this._systemState = matrix;
    this._pivotColumn = undefined;
    this._pivot = {
      row: undefined,
      column: undefined
    };
    this._isEchelonForm = undefined;
    this._isReducedEchelonForm = undefined;
  }
  solve(){
    // 1. the left most non-zero column is the _pivotColumn
    //try first column, iterate until a column has a non-zero int in it
    let isNonZero = false;
    for (var i = 0; i < this._systemState.length; i++) {
      let thisColumn = this._systemState.map(function(value) {
        return value[i];
      });
      isNonZero = thisColumn.some(function(entry){
        return Math.abs(entry) > 0
      });
      if (isNonZero) {
        this._pivotColumn = i;
        break;
      }
    }
    //if there isn't a non-zero column then the set is empty and has no solutions
    if ( undefined === this._pivotColumn) {
      throw 'empty sets have no solutions';
    }
    // 2. the top row/column postion of the _pivotColumn is the _pivot location
    this._pivot.row = 0;
    this._pivot.column = this._pivotColumn;
    // foreach row:
    this._systemState.forEach(function(row, index){
    // a. _largestAbsoluteMovedToTopOfColumn on the _pivotColumn - largest to top
      this._largestAbsoluteMovedToTopOfColumn(this._pivot.column, this._pivot.row);
    });
    console.log(this._systemState);
    // b. _zeroAllRowsUnderThePevot() - row replacement operations to "zero" all entry under the pivot
    // c. _pivot.row++, _pivot.column++
    // 3. foreach row:
    // a. _zeroAllRowsAboveThePivot(), _scalePivotToOne
    // b. _pivot.row--, _pivot--
  }
  _largestAbsoluteMovedToTopOfColumn(columnNumber, rowsOffSetNumber){
    let largestValue = 0;
    let indexOfLargestValue = undefined;
    let columnArray = this._systemState.map(function(value) {
      return value[columnNumber];
    });
    columnArray.forEach(function(value, index){
      if (index >= rowsOffSetNumber) {
        if (Math.abs(value) > largestValue) {
          largestValue = Math.abs(value);
          indexOfLargestValue = index;
        }
      }
    });
    this._switch(this._pivot.row, indexOfLargestValue)
  }
  _switch(aRowNumber, differentRowNumber){
    let holder = this._systemState[differentRowNumber];
    this._systemState[differentRowNumber] = this._systemState[aRowNumber];
    this._systemState[aRowNumber] = holder;
  }
}

const initObject = [
  [2,3,0,5],
  [0,0,1,20],
  [0,-2,0,5]
];

const theSystem = new LinearSystem(initObject);
theSystem.solve();
<commit_msg>update<commit_after>class LinearSystem {
  constructor(matrix) {
    //input should be a array of array of ints
    if ( ! Array.isArray(matrix)) {
      throw 'not array type error';
    }
    const hight = matrix.length;
    matrix.forEach(function(row){
      if ( ! Array.isArray(row)) {
        throw 'not array type error';
      }
      //checks if input matrix is ( column.length + 1 == rows.length )
      if ( hight + 1 != row.length ) {
        throw 'not in required shape (width == hight + 1)';
      }
      row.forEach(function(entry){
        if ( ! Number.isInteger(entry)) {
          throw 'not a integer error';
        }
      });
    });
    this._systemState = matrix;
    this._pivotColumn = undefined;
    this._pivot = {
      row: undefined,
      column: undefined
    };
    this._isEchelonForm = undefined;
    this._isReducedEchelonForm = undefined;
  }
  solve(){
    // 1. the left most non-zero column is the _pivotColumn
    //try first column, iterate until a column has a non-zero int in it
    let isNonZero = false;
    const that = this;
    for (var i = 0; i < this._systemState.length; i++) {
      let thisColumn = this._systemState.map(function(value) {
        return value[i];
      });
      isNonZero = thisColumn.some(function(entry){
        return Math.abs(entry) > 0
      });
      if (isNonZero) {
        this._pivotColumn = i;
        break;
      }
    }
    //if there isn't a non-zero column then the set is empty and has no solutions
    if ( undefined === this._pivotColumn) {
      throw 'empty sets have no solutions';
    }
    // 2. the top row/column postion of the _pivotColumn is the _pivot location
    this._pivot.row = 0;
    this._pivot.column = this._pivotColumn;
    // foreach row:
    this._systemState.forEach(function(row, index){
    // a. _largestAbsoluteMovedToTopOfColumn on the _pivotColumn - largest to top
      that._largestAbsoluteMovedToTopOfColumn(that._pivot.column, that._pivot.row);
    // b. _zeroAllRowsUnderThePevot() - row replacement operations to "zero" all entry under the pivot
    // c. _pivot.row++, _pivot.column++
    });
    // 3. foreach row:
    // a. _zeroAllRowsAboveThePivot(), _scalePivotToOne
    // b. _pivot.row--, _pivot--
  }
  _largestAbsoluteMovedToTopOfColumn(columnNumber, rowsOffSetNumber){
    let largestValue = 0;
    let indexOfLargestValue = undefined;
    let columnArray = this._systemState.map(function(value) {
      return value[columnNumber];
    });
    columnArray.forEach(function(value, index){
      if (index >= rowsOffSetNumber) {
        if (Math.abs(value) > largestValue) {
          largestValue = Math.abs(value);
          indexOfLargestValue = index;
        }
      }
    });
    this._switch(this._pivot.row, indexOfLargestValue)
  }
  _switch(aRowNumber, differentRowNumber){
    let holder = this._systemState[differentRowNumber];
    this._systemState[differentRowNumber] = this._systemState[aRowNumber];
    this._systemState[aRowNumber] = holder;
  }
}

const initObject = [
  [2,3,0,5],
  [0,0,1,20],
  [0,-2,0,5]
];

const theSystem = new LinearSystem(initObject);
theSystem.solve();
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2017 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Object representing a map of variables and their types.
 * @author marisaleung@google.com (Marisa Leung)
 */
'use strict';

goog.provide('Blockly.VariableMap');

goog.require('Blockly.Events');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.VarDelete');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.VarRename');
goog.require('Blockly.Msg');
goog.require('Blockly.utils');
goog.require('Blockly.utils.object');

goog.requireType('Blockly.Block');
goog.requireType('Blockly.VariableModel');
goog.requireType('Blockly.Workspace');

/**
 * Class for a variable map.  This contains a dictionary data structure with
 * variable types as keys and lists of variables as values.  The list of
 * variables are the type indicated by the key.
 * @param {!Blockly.Workspace} workspace The workspace this map belongs to.
 * @constructor
 */
Blockly.VariableMap = function(workspace) {
  /**
   * A map from variable type to list of variable names.  The lists contain all
   * of the named variables in the workspace, including variables
   * that are not currently in use.
   * @type {!Object<string, !Array<Blockly.VariableModel>>}
   * @private
   */
  this.variableMap_ = Object.create(null);

  /**
   * The workspace this map belongs to.
   * @type {!Blockly.Workspace}
   */
  this.workspace = workspace;
};

/**
 * Clear the variable map.
 */
Blockly.VariableMap.prototype.clear = function() {
  this.variableMap_ = Object.create(null);
};

/* Begin functions for renaming variables. */

/**
 * Rename the given variable by updating its name in the variable map.
 * @param {!Blockly.VariableModel} variable Variable to rename.
 * @param {string} newName New variable name.
 * @package
 */
Blockly.VariableMap.prototype.renameVariable = function(variable, newName) {
  var type = variable.type;
  var conflictVar = this.getVariable(newName, type);
  var blocks = this.workspace.getAllBlocks(false);
  Blockly.Events.setGroup(true);
  try {
    // The IDs may match if the rename is a simple case change (name1 -> Name1).
    if (!conflictVar || conflictVar.getId() == variable.getId()) {
      this.renameVariableAndUses_(variable, newName, blocks);
    } else {
      this.renameVariableWithConflict_(variable, newName, conflictVar, blocks);
    }
  } finally {
    Blockly.Events.setGroup(false);
  }
};

/**
 * Rename a variable by updating its name in the variable map. Identify the
 * variable to rename with the given ID.
 * @param {string} id ID of the variable to rename.
 * @param {string} newName New variable name.
 */
Blockly.VariableMap.prototype.renameVariableById = function(id, newName) {
  var variable = this.getVariableById(id);
  if (!variable) {
    throw Error('Tried to rename a variable that didn\'t exist. ID: ' + id);
  }

  this.renameVariable(variable, newName);
};

/**
 * Update the name of the given variable and refresh all references to it.
 * The new name must not conflict with any existing variable names.
 * @param {!Blockly.VariableModel} variable Variable to rename.
 * @param {string} newName New variable name.
 * @param {!Array<!Blockly.Block>} blocks The list of all blocks in the
 *     workspace.
 * @private
 */
Blockly.VariableMap.prototype.renameVariableAndUses_ = function(variable,
    newName, blocks) {
  Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.VAR_RENAME))(
      variable, newName));
  variable.name = newName;
  for (var i = 0; i < blocks.length; i++) {
    blocks[i].updateVarName(variable);
  }
};

/**
 * Update the name of the given variable to the same name as an existing
 * variable.  The two variables are coalesced into a single variable with the ID
 * of the existing variable that was already using newName.
 * Refresh all references to the variable.
 * @param {!Blockly.VariableModel} variable Variable to rename.
 * @param {string} newName New variable name.
 * @param {!Blockly.VariableModel} conflictVar The variable that was already
 *     using newName.
 * @param {!Array<!Blockly.Block>} blocks The list of all blocks in the
 *     workspace.
 * @private
 */
Blockly.VariableMap.prototype.renameVariableWithConflict_ = function(variable,
    newName, conflictVar, blocks) {
  var type = variable.type;
  var oldCase = conflictVar.name;

  if (newName != oldCase) {
    // Simple rename to change the case and update references.
    this.renameVariableAndUses_(conflictVar, newName, blocks);
  }

  // These blocks now refer to a different variable.
  // These will fire change events.
  for (var i = 0; i < blocks.length; i++) {
    blocks[i].renameVarById(variable.getId(), conflictVar.getId());
  }

  // Finally delete the original variable, which is now unreferenced.
  Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.VAR_DELETE))(
      variable));
  // And remove it from the list.
  var variableList = this.getVariablesOfType(type);
  var variableIndex = variableList.indexOf(variable);
  this.variableMap_[type].splice(variableIndex, 1);

};

/* End functions for renaming variables. */

/**
 * Create a variable with a given name, optional type, and optional ID.
 * @param {string} name The name of the variable. This must be unique across
 *     variables and procedures.
 * @param {?string=} opt_type The type of the variable like 'int' or 'string'.
 *     Does not need to be unique. Field_variable can filter variables based on
 *     their type. This will default to '' which is a specific type.
 * @param {?string=} opt_id The unique ID of the variable. This will default to
 *     a UUID.
 * @return {!Blockly.VariableModel} The newly created variable.
 */
Blockly.VariableMap.prototype.createVariable = function(name,
    opt_type, opt_id) {
  var variable = this.getVariable(name, opt_type);
  if (variable) {
    if (opt_id && variable.getId() != opt_id) {
      throw Error('Variable "' + name + '" is already in use and its id is "' +
          variable.getId() + '" which conflicts with the passed in ' +
          'id, "' + opt_id + '".');
    }
    // The variable already exists and has the same ID.
    return variable;
  }
  if (opt_id && this.getVariableById(opt_id)) {
    throw Error('Variable id, "' + opt_id + '", is already in use.');
  }
  var id = opt_id || Blockly.utils.genUid();
  var type = opt_type || '';
  variable = new Blockly.VariableModel(this.workspace, name, type, id);

  var variables = this.variableMap_[type] || [];
  variables.push(variable);
  // Delete the list of variables of this type, and re-add it so that
  // the most recent addition is at the end.
  // This is used so the toolbox's set block is set to the most recent variable.
  delete this.variableMap_[type];
  this.variableMap_[type] = variables;

  return variable;
};

/* Begin functions for variable deletion. */

/**
 * Delete a variable.
 * @param {!Blockly.VariableModel} variable Variable to delete.
 */
Blockly.VariableMap.prototype.deleteVariable = function(variable) {
  var variableList = this.variableMap_[variable.type];
  for (var i = 0, tempVar; (tempVar = variableList[i]); i++) {
    if (tempVar.getId() == variable.getId()) {
      variableList.splice(i, 1);
      Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.VAR_DELETE))(
          variable));
      return;
    }
  }
};

/**
 * Delete a variables by the passed in ID and all of its uses from this
 * workspace. May prompt the user for confirmation.
 * @param {string} id ID of variable to delete.
 */
Blockly.VariableMap.prototype.deleteVariableById = function(id) {
  var variable = this.getVariableById(id);
  if (variable) {
    // Check whether this variable is a function parameter before deleting.
    var variableName = variable.name;
    var uses = this.getVariableUsesById(id);
    for (var i = 0, block; (block = uses[i]); i++) {
      if (block.type == 'procedures_defnoreturn' ||
        block.type == 'procedures_defreturn') {
        var procedureName = block.getFieldValue('NAME');
        var deleteText = Blockly.Msg['CANNOT_DELETE_VARIABLE_PROCEDURE'].
            replace('%1', variableName).
            replace('%2', procedureName);
        Blockly.alert(deleteText);
        return;
      }
    }

    var map = this;
    if (uses.length > 1) {
      // Confirm before deleting multiple blocks.
      var confirmText = Blockly.Msg['DELETE_VARIABLE_CONFIRMATION'].
          replace('%1', String(uses.length)).
          replace('%2', variableName);
      Blockly.confirm(confirmText,
          function(ok) {
            if (ok && variable) {
              map.deleteVariableInternal(variable, uses);
            }
          });
    } else {
      // No confirmation necessary for a single block.
      map.deleteVariableInternal(variable, uses);
    }
  } else {
    console.warn("Can't delete non-existent variable: " + id);
  }
};

/**
 * Deletes a variable and all of its uses from this workspace without asking the
 * user for confirmation.
 * @param {!Blockly.VariableModel} variable Variable to delete.
 * @param {!Array<!Blockly.Block>} uses An array of uses of the variable.
 * @package
 */
Blockly.VariableMap.prototype.deleteVariableInternal = function(variable,
    uses) {
  var existingGroup = Blockly.Events.getGroup();
  if (!existingGroup) {
    Blockly.Events.setGroup(true);
  }
  try {
    for (var i = 0; i < uses.length; i++) {
      uses[i].dispose(true);
    }
    this.deleteVariable(variable);
  } finally {
    if (!existingGroup) {
      Blockly.Events.setGroup(false);
    }
  }
};

/* End functions for variable deletion. */

/**
 * Find the variable by the given name and type and return it.  Return null if
 *     it is not found.
 * @param {string} name The name to check for.
 * @param {?string=} opt_type The type of the variable.  If not provided it
 *     defaults to the empty string, which is a specific type.
 * @return {?Blockly.VariableModel} The variable with the given name, or null if
 *     it was not found.
 */
Blockly.VariableMap.prototype.getVariable = function(name, opt_type) {
  var type = opt_type || '';
  var list = this.variableMap_[type];
  if (list) {
    for (var j = 0, variable; (variable = list[j]); j++) {
      if (Blockly.Names.equals(variable.name, name)) {
        return variable;
      }
    }
  }
  return null;
};

/**
 * Find the variable by the given ID and return it.  Return null if not found.
 * @param {string} id The ID to check for.
 * @return {?Blockly.VariableModel} The variable with the given ID.
 */
Blockly.VariableMap.prototype.getVariableById = function(id) {
  var keys = Object.keys(this.variableMap_);
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    for (var j = 0, variable; (variable = this.variableMap_[key][j]); j++) {
      if (variable.getId() == id) {
        return variable;
      }
    }
  }
  return null;
};

/**
 * Get a list containing all of the variables of a specified type. If type is
 *     null, return list of variables with empty string type.
 * @param {?string} type Type of the variables to find.
 * @return {!Array<!Blockly.VariableModel>} The sought after variables of the
 *     passed in type. An empty array if none are found.
 */
Blockly.VariableMap.prototype.getVariablesOfType = function(type) {
  type = type || '';
  var variable_list = this.variableMap_[type];
  if (variable_list) {
    return variable_list.slice();
  }
  return [];
};

/**
 * Return all variable and potential variable types.  This list always contains
 * the empty string.
 * @param {?Blockly.Workspace} ws The workspace used to look for potential
 * variables. This can be different than the workspace stored on this object
 * if the passed in ws is a flyout workspace.
 * @return {!Array<string>} List of variable types.
 * @package
 */
Blockly.VariableMap.prototype.getVariableTypes = function(ws) {
  var variableMap = {};
  Blockly.utils.object.mixin(variableMap, this.variableMap_);
  if (ws && ws.getPotentialVariableMap()) {
    Blockly.utils.object.mixin(variableMap,
        ws.getPotentialVariableMap().variableMap_);
  }
  var types = Object.keys(variableMap);
  var hasEmpty = false;
  for (var i = 0; i < types.length; i++) {
    if (types[i] == '') {
      hasEmpty = true;
    }
  }
  if (!hasEmpty) {
    types.push('');
  }
  return types;
};

/**
 * Return all variables of all types.
 * @return {!Array<!Blockly.VariableModel>} List of variable models.
 */
Blockly.VariableMap.prototype.getAllVariables = function() {
  var all_variables = [];
  for (var key in this.variableMap_) {
    all_variables = all_variables.concat(this.variableMap_[key]);
  }
  return all_variables;
};

/**
 * Returns all of the variable names of all types.
 * @return {!Array<string>} All of the variable names of all types.
 */
Blockly.VariableMap.prototype.getAllVariableNames = function() {
  var allNames = [];
  for (var key in this.variableMap_) {
    var variables = this.variableMap_[key];
    for (var i = 0, variable; (variable = variables[i]); i++) {
      allNames.push(variable.name);
    }
  }
  return allNames;
};

/**
 * Find all the uses of a named variable.
 * @param {string} id ID of the variable to find.
 * @return {!Array<!Blockly.Block>} Array of block usages.
 */
Blockly.VariableMap.prototype.getVariableUsesById = function(id) {
  var uses = [];
  var blocks = this.workspace.getAllBlocks(false);
  // Iterate through every block and check the name.
  for (var i = 0; i < blocks.length; i++) {
    var blockVariables = blocks[i].getVarModels();
    if (blockVariables) {
      for (var j = 0; j < blockVariables.length; j++) {
        if (blockVariables[j].getId() == id) {
          uses.push(blocks[i]);
        }
      }
    }
  }
  return uses;
};
<commit_msg>Migrate core/variable_map.js to ES6 const/let<commit_after>/**
 * @license
 * Copyright 2017 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Object representing a map of variables and their types.
 * @author marisaleung@google.com (Marisa Leung)
 */
'use strict';

goog.provide('Blockly.VariableMap');

goog.require('Blockly.Events');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.VarDelete');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.VarRename');
goog.require('Blockly.Msg');
goog.require('Blockly.utils');
goog.require('Blockly.utils.object');

goog.requireType('Blockly.Block');
goog.requireType('Blockly.VariableModel');
goog.requireType('Blockly.Workspace');

/**
 * Class for a variable map.  This contains a dictionary data structure with
 * variable types as keys and lists of variables as values.  The list of
 * variables are the type indicated by the key.
 * @param {!Blockly.Workspace} workspace The workspace this map belongs to.
 * @constructor
 */
Blockly.VariableMap = function(workspace) {
  /**
   * A map from variable type to list of variable names.  The lists contain all
   * of the named variables in the workspace, including variables
   * that are not currently in use.
   * @type {!Object<string, !Array<Blockly.VariableModel>>}
   * @private
   */
  this.variableMap_ = Object.create(null);

  /**
   * The workspace this map belongs to.
   * @type {!Blockly.Workspace}
   */
  this.workspace = workspace;
};

/**
 * Clear the variable map.
 */
Blockly.VariableMap.prototype.clear = function() {
  this.variableMap_ = Object.create(null);
};

/* Begin functions for renaming variables. */

/**
 * Rename the given variable by updating its name in the variable map.
 * @param {!Blockly.VariableModel} variable Variable to rename.
 * @param {string} newName New variable name.
 * @package
 */
Blockly.VariableMap.prototype.renameVariable = function(variable, newName) {
  const type = variable.type;
  const conflictVar = this.getVariable(newName, type);
  const blocks = this.workspace.getAllBlocks(false);
  Blockly.Events.setGroup(true);
  try {
    // The IDs may match if the rename is a simple case change (name1 -> Name1).
    if (!conflictVar || conflictVar.getId() == variable.getId()) {
      this.renameVariableAndUses_(variable, newName, blocks);
    } else {
      this.renameVariableWithConflict_(variable, newName, conflictVar, blocks);
    }
  } finally {
    Blockly.Events.setGroup(false);
  }
};

/**
 * Rename a variable by updating its name in the variable map. Identify the
 * variable to rename with the given ID.
 * @param {string} id ID of the variable to rename.
 * @param {string} newName New variable name.
 */
Blockly.VariableMap.prototype.renameVariableById = function(id, newName) {
  const variable = this.getVariableById(id);
  if (!variable) {
    throw Error('Tried to rename a variable that didn\'t exist. ID: ' + id);
  }

  this.renameVariable(variable, newName);
};

/**
 * Update the name of the given variable and refresh all references to it.
 * The new name must not conflict with any existing variable names.
 * @param {!Blockly.VariableModel} variable Variable to rename.
 * @param {string} newName New variable name.
 * @param {!Array<!Blockly.Block>} blocks The list of all blocks in the
 *     workspace.
 * @private
 */
Blockly.VariableMap.prototype.renameVariableAndUses_ = function(variable,
    newName, blocks) {
  Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.VAR_RENAME))(
      variable, newName));
  variable.name = newName;
  for (let i = 0; i < blocks.length; i++) {
    blocks[i].updateVarName(variable);
  }
};

/**
 * Update the name of the given variable to the same name as an existing
 * variable.  The two variables are coalesced into a single variable with the ID
 * of the existing variable that was already using newName.
 * Refresh all references to the variable.
 * @param {!Blockly.VariableModel} variable Variable to rename.
 * @param {string} newName New variable name.
 * @param {!Blockly.VariableModel} conflictVar The variable that was already
 *     using newName.
 * @param {!Array<!Blockly.Block>} blocks The list of all blocks in the
 *     workspace.
 * @private
 */
Blockly.VariableMap.prototype.renameVariableWithConflict_ = function(variable,
    newName, conflictVar, blocks) {
  const type = variable.type;
  const oldCase = conflictVar.name;

  if (newName != oldCase) {
    // Simple rename to change the case and update references.
    this.renameVariableAndUses_(conflictVar, newName, blocks);
  }

  // These blocks now refer to a different variable.
  // These will fire change events.
  for (let i = 0; i < blocks.length; i++) {
    blocks[i].renameVarById(variable.getId(), conflictVar.getId());
  }

  // Finally delete the original variable, which is now unreferenced.
  Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.VAR_DELETE))(
      variable));
  // And remove it from the list.
  const variableList = this.getVariablesOfType(type);
  const variableIndex = variableList.indexOf(variable);
  this.variableMap_[type].splice(variableIndex, 1);

};

/* End functions for renaming variables. */

/**
 * Create a variable with a given name, optional type, and optional ID.
 * @param {string} name The name of the variable. This must be unique across
 *     variables and procedures.
 * @param {?string=} opt_type The type of the variable like 'int' or 'string'.
 *     Does not need to be unique. Field_variable can filter variables based on
 *     their type. This will default to '' which is a specific type.
 * @param {?string=} opt_id The unique ID of the variable. This will default to
 *     a UUID.
 * @return {!Blockly.VariableModel} The newly created variable.
 */
Blockly.VariableMap.prototype.createVariable = function(name,
    opt_type, opt_id) {
  let variable = this.getVariable(name, opt_type);
  if (variable) {
    if (opt_id && variable.getId() != opt_id) {
      throw Error('Variable "' + name + '" is already in use and its id is "' +
          variable.getId() + '" which conflicts with the passed in ' +
          'id, "' + opt_id + '".');
    }
    // The variable already exists and has the same ID.
    return variable;
  }
  if (opt_id && this.getVariableById(opt_id)) {
    throw Error('Variable id, "' + opt_id + '", is already in use.');
  }
  const id = opt_id || Blockly.utils.genUid();
  const type = opt_type || '';
  variable = new Blockly.VariableModel(this.workspace, name, type, id);

  const variables = this.variableMap_[type] || [];
  variables.push(variable);
  // Delete the list of variables of this type, and re-add it so that
  // the most recent addition is at the end.
  // This is used so the toolbox's set block is set to the most recent variable.
  delete this.variableMap_[type];
  this.variableMap_[type] = variables;

  return variable;
};

/* Begin functions for variable deletion. */

/**
 * Delete a variable.
 * @param {!Blockly.VariableModel} variable Variable to delete.
 */
Blockly.VariableMap.prototype.deleteVariable = function(variable) {
  const variableList = this.variableMap_[variable.type];
  for (let i = 0, tempVar; (tempVar = variableList[i]); i++) {
    if (tempVar.getId() == variable.getId()) {
      variableList.splice(i, 1);
      Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.VAR_DELETE))(
          variable));
      return;
    }
  }
};

/**
 * Delete a variables by the passed in ID and all of its uses from this
 * workspace. May prompt the user for confirmation.
 * @param {string} id ID of variable to delete.
 */
Blockly.VariableMap.prototype.deleteVariableById = function(id) {
  const variable = this.getVariableById(id);
  if (variable) {
    // Check whether this variable is a function parameter before deleting.
    const variableName = variable.name;
    const uses = this.getVariableUsesById(id);
    for (let i = 0, block; (block = uses[i]); i++) {
      if (block.type == 'procedures_defnoreturn' ||
        block.type == 'procedures_defreturn') {
        const procedureName = block.getFieldValue('NAME');
        const deleteText = Blockly.Msg['CANNOT_DELETE_VARIABLE_PROCEDURE'].
            replace('%1', variableName).
            replace('%2', procedureName);
        Blockly.alert(deleteText);
        return;
      }
    }

    const map = this;
    if (uses.length > 1) {
      // Confirm before deleting multiple blocks.
      const confirmText = Blockly.Msg['DELETE_VARIABLE_CONFIRMATION'].
          replace('%1', String(uses.length)).
          replace('%2', variableName);
      Blockly.confirm(confirmText,
          function(ok) {
            if (ok && variable) {
              map.deleteVariableInternal(variable, uses);
            }
          });
    } else {
      // No confirmation necessary for a single block.
      map.deleteVariableInternal(variable, uses);
    }
  } else {
    console.warn("Can't delete non-existent variable: " + id);
  }
};

/**
 * Deletes a variable and all of its uses from this workspace without asking the
 * user for confirmation.
 * @param {!Blockly.VariableModel} variable Variable to delete.
 * @param {!Array<!Blockly.Block>} uses An array of uses of the variable.
 * @package
 */
Blockly.VariableMap.prototype.deleteVariableInternal = function(variable,
    uses) {
  const existingGroup = Blockly.Events.getGroup();
  if (!existingGroup) {
    Blockly.Events.setGroup(true);
  }
  try {
    for (let i = 0; i < uses.length; i++) {
      uses[i].dispose(true);
    }
    this.deleteVariable(variable);
  } finally {
    if (!existingGroup) {
      Blockly.Events.setGroup(false);
    }
  }
};

/* End functions for variable deletion. */

/**
 * Find the variable by the given name and type and return it.  Return null if
 *     it is not found.
 * @param {string} name The name to check for.
 * @param {?string=} opt_type The type of the variable.  If not provided it
 *     defaults to the empty string, which is a specific type.
 * @return {?Blockly.VariableModel} The variable with the given name, or null if
 *     it was not found.
 */
Blockly.VariableMap.prototype.getVariable = function(name, opt_type) {
  const type = opt_type || '';
  const list = this.variableMap_[type];
  if (list) {
    for (let j = 0, variable; (variable = list[j]); j++) {
      if (Blockly.Names.equals(variable.name, name)) {
        return variable;
      }
    }
  }
  return null;
};

/**
 * Find the variable by the given ID and return it.  Return null if not found.
 * @param {string} id The ID to check for.
 * @return {?Blockly.VariableModel} The variable with the given ID.
 */
Blockly.VariableMap.prototype.getVariableById = function(id) {
  const keys = Object.keys(this.variableMap_);
  for (let i = 0; i < keys.length; i++) {
    const key = keys[i];
    for (let j = 0, variable; (variable = this.variableMap_[key][j]); j++) {
      if (variable.getId() == id) {
        return variable;
      }
    }
  }
  return null;
};

/**
 * Get a list containing all of the variables of a specified type. If type is
 *     null, return list of variables with empty string type.
 * @param {?string} type Type of the variables to find.
 * @return {!Array<!Blockly.VariableModel>} The sought after variables of the
 *     passed in type. An empty array if none are found.
 */
Blockly.VariableMap.prototype.getVariablesOfType = function(type) {
  type = type || '';
  const variable_list = this.variableMap_[type];
  if (variable_list) {
    return variable_list.slice();
  }
  return [];
};

/**
 * Return all variable and potential variable types.  This list always contains
 * the empty string.
 * @param {?Blockly.Workspace} ws The workspace used to look for potential
 * variables. This can be different than the workspace stored on this object
 * if the passed in ws is a flyout workspace.
 * @return {!Array<string>} List of variable types.
 * @package
 */
Blockly.VariableMap.prototype.getVariableTypes = function(ws) {
  const variableMap = {};
  Blockly.utils.object.mixin(variableMap, this.variableMap_);
  if (ws && ws.getPotentialVariableMap()) {
    Blockly.utils.object.mixin(variableMap,
        ws.getPotentialVariableMap().variableMap_);
  }
  const types = Object.keys(variableMap);
  let hasEmpty = false;
  for (let i = 0; i < types.length; i++) {
    if (types[i] == '') {
      hasEmpty = true;
    }
  }
  if (!hasEmpty) {
    types.push('');
  }
  return types;
};

/**
 * Return all variables of all types.
 * @return {!Array<!Blockly.VariableModel>} List of variable models.
 */
Blockly.VariableMap.prototype.getAllVariables = function() {
  let all_variables = [];
  for (const key in this.variableMap_) {
    all_variables = all_variables.concat(this.variableMap_[key]);
  }
  return all_variables;
};

/**
 * Returns all of the variable names of all types.
 * @return {!Array<string>} All of the variable names of all types.
 */
Blockly.VariableMap.prototype.getAllVariableNames = function() {
  const allNames = [];
  for (const key in this.variableMap_) {
    const variables = this.variableMap_[key];
    for (let i = 0, variable; (variable = variables[i]); i++) {
      allNames.push(variable.name);
    }
  }
  return allNames;
};

/**
 * Find all the uses of a named variable.
 * @param {string} id ID of the variable to find.
 * @return {!Array<!Blockly.Block>} Array of block usages.
 */
Blockly.VariableMap.prototype.getVariableUsesById = function(id) {
  const uses = [];
  const blocks = this.workspace.getAllBlocks(false);
  // Iterate through every block and check the name.
  for (let i = 0; i < blocks.length; i++) {
    const blockVariables = blocks[i].getVarModels();
    if (blockVariables) {
      for (let j = 0; j < blockVariables.length; j++) {
        if (blockVariables[j].getId() == id) {
          uses.push(blocks[i]);
        }
      }
    }
  }
  return uses;
};
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Mathieu Turcotte
 * Licensed under the MIT license.
 */

var events = require('events'),
    util = require('util');

var testCase = require('nodeunit').testCase,
    assert = require('nodeunit').assert,
    sinon = require('sinon');

var Level = require('../lib/level'),
    Logger = require('../lib/logger'),
    Record = require('../lib/record'),
    Handler = require('../lib/handler/handler');

assert.hasAttributes = function(obj, attributes, message) {
    for (var name in attributes) {
        if (obj[name] != attributes[name]) {
            assert.fail(obj[name], attributes[name], message, '==');
        }
    }
};

function publishedRecord(handler) {
    return handler.publish.getCall(0).args[0];
};

exports["Logger"] = testCase({
    setUp: function(callback) {
        this.exception = new Error('error message');
        this.handler = sinon.stub(new Handler());
        this.logger = new Logger('foo.bar.biz');
        this.logger.addHandler(this.handler);
        callback();
    },

    "fatal method should log at Level.FATAL": function(test) {
        this.logger.fatal('message');

        test.hasAttributes(publishedRecord(this.handler), {
            level: Level.FATAL,
            message: 'message',
            loggerName: 'foo.bar.biz',
        });
        test.done();
    },

    "error method should log at Level.ERROR": function(test) {
        this.logger.error('message');

        test.hasAttributes(publishedRecord(this.handler), {
            level: Level.ERROR,
            message: 'message',
            loggerName: 'foo.bar.biz',
        });
        test.done();
    },

    "severe method should log at Level.SEVERE": function(test) {
        this.logger.severe('message');

        test.hasAttributes(publishedRecord(this.handler), {
            level: Level.SEVERE,
            message: 'message',
            loggerName: 'foo.bar.biz',
        });
        test.done();
    },

    "warning method should log at Level.WARNING": function(test) {
        this.logger.warning('message');

        test.hasAttributes(publishedRecord(this.handler), {
            level: Level.WARNING,
            message: 'message',
            loggerName: 'foo.bar.biz',
        });
        test.done();
    },

    "notice method should log at Level.NOTICE": function(test) {
        this.logger.notice('message');

        test.hasAttributes(publishedRecord(this.handler), {
            level: Level.NOTICE,
            message: 'message',
            loggerName: 'foo.bar.biz',
        });
        test.done();
    },

    "info method should log at Level.INFO": function(test) {
        this.logger.info('message');

        test.hasAttributes(publishedRecord(this.handler), {
            level: Level.INFO,
            message: 'message',
            loggerName: 'foo.bar.biz',
        });
        test.done();
    },

    "config method should log at Level.CONFIG": function(test) {
        this.logger.config('message');

        test.hasAttributes(publishedRecord(this.handler), {
            level: Level.CONFIG,
            message: 'message',
            loggerName: 'foo.bar.biz',
        });
        test.done();
    },

    "debug method should log at Level.DEBUG": function(test) {
        this.logger.debug('message');

        test.hasAttributes(publishedRecord(this.handler), {
            level: Level.DEBUG,
            message: 'message',
            loggerName: 'foo.bar.biz',
        });
        test.done();
    }
});
<commit_msg>Update logger methods tests.<commit_after>/*
 * Copyright (c) 2012 Mathieu Turcotte
 * Licensed under the MIT license.
 */

var events = require('events'),
    util = require('util');

var testCase = require('nodeunit').testCase,
    assert = require('nodeunit').assert,
    sinon = require('sinon');

var Level = require('../lib/level'),
    Logger = require('../lib/logger'),
    Record = require('../lib/record'),
    Handler = require('../lib/handler/handler');

function publishedRecord(handler) {
    return handler.publish.getCall(0).args[0];
};

var LOGGER_NAME = 'foo.bar.biz',
    DATE_NOW = 1234567;

exports["Logger"] = testCase({
    setUp: function(callback) {
        this.clock = sinon.useFakeTimers(DATE_NOW);
        this.handler = sinon.stub(new Handler());
        this.logger = new Logger(LOGGER_NAME);
        this.logger.addHandler(this.handler);
        callback();
    },

    tearDown: function(callback) {
        this.clock.restore();
        callback();
    },

    "fatal method should log at Level.FATAL": function(test) {
        this.logger.fatal('message');

        var record = publishedRecord(this.handler);
        test.deepEqual(record.level, Level.FATAL);
        test.done();
    },

    "error method should log at Level.ERROR": function(test) {
        this.logger.error('message');

        var record = publishedRecord(this.handler);
        test.deepEqual(record.level, Level.ERROR);
        test.done();
    },

    "severe method should log at Level.SEVERE": function(test) {
        this.logger.severe('message');

        var record = publishedRecord(this.handler);
        test.deepEqual(record.level, Level.SEVERE);
        test.done();
    },

    "warning method should log at Level.WARNING": function(test) {
        this.logger.warning('message');

        var record = publishedRecord(this.handler);
        test.deepEqual(record.level, Level.WARNING);
        test.done();
    },

    "notice method should log at Level.NOTICE": function(test) {
        this.logger.notice('message');

        var record = publishedRecord(this.handler);
        test.deepEqual(record.level, Level.NOTICE);
        test.done();
    },

    "info method should log at Level.INFO": function(test) {
        this.logger.info('message');

        var record = publishedRecord(this.handler);
        test.deepEqual(record.level, Level.INFO);
        test.done();
    },

    "config method should log at Level.CONFIG": function(test) {
        this.logger.config('message');

        var record = publishedRecord(this.handler);
        test.deepEqual(record.level, Level.CONFIG);
        test.done();
    },

    "debug method should log at Level.DEBUG": function(test) {
        this.logger.debug('message');

        var record = publishedRecord(this.handler);
        test.deepEqual(record.level, Level.DEBUG);
        test.done();
    },

    "fatal method should log a formatted message": function(test) {
        this.logger.fatal('message %d %s', 1, 'abc');

        var record = publishedRecord(this.handler);
        test.equals(record.message, 'message 1 abc');
        test.done();
    },

    "error method should log a formatted message": function(test) {
        this.logger.error('message %d %s', 1, 'abc');

        var record = publishedRecord(this.handler);
        test.equals(record.message, 'message 1 abc');
        test.done();
    },

    "severe method should log a formatted message": function(test) {
        this.logger.severe('message %d %s', 1, 'abc');

        var record = publishedRecord(this.handler);
        test.equals(record.message, 'message 1 abc');
        test.done();
    },

    "warning method should log a formatted message": function(test) {
        this.logger.warning('message %d %s', 1, 'abc');

        var record = publishedRecord(this.handler);
        test.equals(record.message, 'message 1 abc');
        test.done();
    },

    "notice method should log a formatted message": function(test) {
        this.logger.notice('message %d %s', 1, 'abc');

        var record = publishedRecord(this.handler);
        test.equals(record.message, 'message 1 abc');
        test.done();
    },

    "info method should log a formatted message": function(test) {
        this.logger.info('message %d %s', 1, 'abc');

        var record = publishedRecord(this.handler);
        test.equals(record.message, 'message 1 abc');
        test.done();
    },

    "config method should log a formatted message": function(test) {
        this.logger.config('message %d %s', 1, 'abc');

        var record = publishedRecord(this.handler);
        test.equals(record.message, 'message 1 abc');
        test.done();
    },

    "debug method should log a formatted message": function(test) {
        this.logger.debug('message %d %s', 1, 'abc');

        var record = publishedRecord(this.handler);
        test.equals(record.message, 'message 1 abc');
        test.done();
    },

    "logged records should contain the logger name": function(test) {
        this.logger.log(Level.INFO, 'message');

        var record = publishedRecord(this.handler);
        test.equals(record.loggerName, LOGGER_NAME);
        test.done();
    },

    "logged records should contain the current time": function(test) {
        this.logger.log(Level.INFO, 'message');

        var record = publishedRecord(this.handler);
        test.equals(record.time, DATE_NOW);
        test.done();
    }
});
<|endoftext|>