<commit_before>

test( "jQuery.browser", function() {

ok(false, "add some tests");

});

test("jQuery.sub() - Static Methods", function(){
	expect( 18 );
	var Subclass = jQuery.sub();
	Subclass.extend({
		"topLevelMethod": function() {return this.debug;},
		"debug": false,
		"config": {
			"locale": "en_US"
		},
		"setup": function(config) {
			this.extend(true, this["config"], config);
		}
	});
	Subclass.fn.extend({"subClassMethod": function() { return this;}});

	//Test Simple Subclass
	ok(Subclass["topLevelMethod"]() === false, "Subclass.topLevelMethod thought debug was true");
	ok(Subclass["config"]["locale"] == "en_US", Subclass["config"]["locale"] + " is wrong!");
	deepEqual(Subclass["config"]["test"], undefined, "Subclass.config.test is set incorrectly");
	equal(jQuery.ajax, Subclass.ajax, "The subclass failed to get all top level methods");

	//Create a SubSubclass
	var SubSubclass = Subclass.sub();

	//Make Sure the SubSubclass inherited properly
	ok(SubSubclass["topLevelMethod"]() === false, "SubSubclass.topLevelMethod thought debug was true");
	ok(SubSubclass["config"]["locale"] == "en_US", SubSubclass["config"]["locale"] + " is wrong!");
	deepEqual(SubSubclass["config"]["test"], undefined, "SubSubclass.config.test is set incorrectly");
	equal(jQuery.ajax, SubSubclass.ajax, "The subsubclass failed to get all top level methods");

	//Modify The Subclass and test the Modifications
	SubSubclass.fn.extend({"subSubClassMethod": function() { return this;}});
	SubSubclass["setup"]({"locale": "es_MX", "test": "worked"});
	SubSubclass["debug"] = true;
	SubSubclass.ajax = function() {return false;};
	ok(SubSubclass["topLevelMethod"](), "SubSubclass.topLevelMethod thought debug was false");
	deepEqual(SubSubclass(document)["subClassMethod"], Subclass.fn["subClassMethod"], "Methods Differ!");
	ok(SubSubclass["config"]["locale"] == "es_MX", SubSubclass["config"]["locale"] + " is wrong!");
	ok(SubSubclass["config"]["test"] == "worked", "SubSubclass.config.test is set incorrectly");
	notEqual(jQuery.ajax, SubSubclass.ajax, "The subsubclass failed to get all top level methods");

	//This shows that the modifications to the SubSubClass did not bubble back up to it's superclass
	ok(Subclass["topLevelMethod"]() === false, "Subclass.topLevelMethod thought debug was true");
	ok(Subclass["config"]["locale"] == "en_US", Subclass["config"]["locale"] + " is wrong!");
	deepEqual(Subclass["config"]["test"], undefined, "Subclass.config.test is set incorrectly");
	deepEqual(Subclass(document)["subSubClassMethod"], undefined, "subSubClassMethod set incorrectly");
	equal(jQuery.ajax, Subclass.ajax, "The subclass failed to get all top level methods");
});

test("jQuery.sub() - .fn Methods", function(){
	expect( 378 );

	var Subclass = jQuery.sub(),
			SubclassSubclass = Subclass.sub(),
			jQueryDocument = jQuery(document),
			selectors, contexts, methods, method, arg, description;

	jQueryDocument.toString = function(){ return "jQueryDocument"; };

	Subclass.fn.subclassMethod = function(){};
	SubclassSubclass.fn.subclassSubclassMethod = function(){};

	selectors = [
		"body",
		"html, body",
		"

"
	];

	contexts = [undefined, document, jQueryDocument];

	jQuery.expandedEach = jQuery.each;
	jQuery.each(selectors, function(i, selector){

		jQuery.expandedEach({ // all methods that return a new jQuery instance
			"eq": 1 ,
			"add": document,
			"end": undefined,
			"has": undefined,
			"closest": "div",
			"filter": document,
			"find": "div"
		}, function(method, arg){
			jQuery.each(contexts, function(i, context){

				description = "(\""+selector+"\", "+context+")."+method+"("+(arg||"")+")";

				deepEqual(
					(function(var_args){ return jQuery.fn[method].apply(jQuery(selector, context), arguments).subclassMethod; })(arg),
					undefined, "jQuery"+description+" doesn't have Subclass methods"
				);
				deepEqual(
					(function(var_args){ return jQuery.fn[method].apply(jQuery(selector, context), arguments).subclassSubclassMethod; })(arg),
					undefined, "jQuery"+description+" doesn't have SubclassSubclass methods"
				);
				deepEqual(
					Subclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
					"Subclass"+description+" has Subclass methods"
				);
				deepEqual(
					Subclass(selector, context)[method](arg).subclassSubclassMethod, undefined,
					"Subclass"+description+" doesn't have SubclassSubclass methods"
				);
				deepEqual(
					SubclassSubclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
					"SubclassSubclass"+description+" has Subclass methods"
				);
				deepEqual(
					SubclassSubclass(selector, context)[method](arg).subclassSubclassMethod, SubclassSubclass.fn.subclassSubclassMethod,
					"SubclassSubclass"+description+" has SubclassSubclass methods"
				);

			});
		});
	});

});
<commit_msg>Add basic jQuery.browser sanity check.<commit_after>

test( "jQuery.browser", function() {
	expect( 3 );
	var p, haveBool = false;

	ok( jQuery.browser, "jQuery.browser present" );
	ok( jQuery.browser.version, "have a browser version" );
	for ( p in jQuery.browser ) {
		if ( typeof jQuery.browser[ p ] === "boolean" ) {
			haveBool = true;
			break;
		}
	}
	ok( haveBool, "at least 1 Boolean property" );
});

test("jQuery.sub() - Static Methods", function(){
	expect( 18 );
	var Subclass = jQuery.sub();
	Subclass.extend({
		"topLevelMethod": function() {return this.debug;},
		"debug": false,
		"config": {
			"locale": "en_US"
		},
		"setup": function(config) {
			this.extend(true, this["config"], config);
		}
	});
	Subclass.fn.extend({"subClassMethod": function() { return this;}});

	//Test Simple Subclass
	ok(Subclass["topLevelMethod"]() === false, "Subclass.topLevelMethod thought debug was true");
	ok(Subclass["config"]["locale"] == "en_US", Subclass["config"]["locale"] + " is wrong!");
	deepEqual(Subclass["config"]["test"], undefined, "Subclass.config.test is set incorrectly");
	equal(jQuery.ajax, Subclass.ajax, "The subclass failed to get all top level methods");

	//Create a SubSubclass
	var SubSubclass = Subclass.sub();

	//Make Sure the SubSubclass inherited properly
	ok(SubSubclass["topLevelMethod"]() === false, "SubSubclass.topLevelMethod thought debug was true");
	ok(SubSubclass["config"]["locale"] == "en_US", SubSubclass["config"]["locale"] + " is wrong!");
	deepEqual(SubSubclass["config"]["test"], undefined, "SubSubclass.config.test is set incorrectly");
	equal(jQuery.ajax, SubSubclass.ajax, "The subsubclass failed to get all top level methods");

	//Modify The Subclass and test the Modifications
	SubSubclass.fn.extend({"subSubClassMethod": function() { return this;}});
	SubSubclass["setup"]({"locale": "es_MX", "test": "worked"});
	SubSubclass["debug"] = true;
	SubSubclass.ajax = function() {return false;};
	ok(SubSubclass["topLevelMethod"](), "SubSubclass.topLevelMethod thought debug was false");
	deepEqual(SubSubclass(document)["subClassMethod"], Subclass.fn["subClassMethod"], "Methods Differ!");
	ok(SubSubclass["config"]["locale"] == "es_MX", SubSubclass["config"]["locale"] + " is wrong!");
	ok(SubSubclass["config"]["test"] == "worked", "SubSubclass.config.test is set incorrectly");
	notEqual(jQuery.ajax, SubSubclass.ajax, "The subsubclass failed to get all top level methods");

	//This shows that the modifications to the SubSubClass did not bubble back up to it's superclass
	ok(Subclass["topLevelMethod"]() === false, "Subclass.topLevelMethod thought debug was true");
	ok(Subclass["config"]["locale"] == "en_US", Subclass["config"]["locale"] + " is wrong!");
	deepEqual(Subclass["config"]["test"], undefined, "Subclass.config.test is set incorrectly");
	deepEqual(Subclass(document)["subSubClassMethod"], undefined, "subSubClassMethod set incorrectly");
	equal(jQuery.ajax, Subclass.ajax, "The subclass failed to get all top level methods");
});

test("jQuery.sub() - .fn Methods", function(){
	expect( 378 );

	var Subclass = jQuery.sub(),
			SubclassSubclass = Subclass.sub(),
			jQueryDocument = jQuery(document),
			selectors, contexts, methods, method, arg, description;

	jQueryDocument.toString = function(){ return "jQueryDocument"; };

	Subclass.fn.subclassMethod = function(){};
	SubclassSubclass.fn.subclassSubclassMethod = function(){};

	selectors = [
		"body",
		"html, body",
		"

"
	];

	contexts = [undefined, document, jQueryDocument];

	jQuery.expandedEach = jQuery.each;
	jQuery.each(selectors, function(i, selector){

		jQuery.expandedEach({ // all methods that return a new jQuery instance
			"eq": 1 ,
			"add": document,
			"end": undefined,
			"has": undefined,
			"closest": "div",
			"filter": document,
			"find": "div"
		}, function(method, arg){
			jQuery.each(contexts, function(i, context){

				description = "(\""+selector+"\", "+context+")."+method+"("+(arg||"")+")";

				deepEqual(
					(function(var_args){ return jQuery.fn[method].apply(jQuery(selector, context), arguments).subclassMethod; })(arg),
					undefined, "jQuery"+description+" doesn't have Subclass methods"
				);
				deepEqual(
					(function(var_args){ return jQuery.fn[method].apply(jQuery(selector, context), arguments).subclassSubclassMethod; })(arg),
					undefined, "jQuery"+description+" doesn't have SubclassSubclass methods"
				);
				deepEqual(
					Subclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
					"Subclass"+description+" has Subclass methods"
				);
				deepEqual(
					Subclass(selector, context)[method](arg).subclassSubclassMethod, undefined,
					"Subclass"+description+" doesn't have SubclassSubclass methods"
				);
				deepEqual(
					SubclassSubclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
					"SubclassSubclass"+description+" has Subclass methods"
				);
				deepEqual(
					SubclassSubclass(selector, context)[method](arg).subclassSubclassMethod, SubclassSubclass.fn.subclassSubclassMethod,
					"SubclassSubclass"+description+" has SubclassSubclass methods"
				);

			});
		});
	});

});
<|endoftext|>


<commit_before>/**
 * Game Idea Machine
 * a twitter bot which tweets random game ideas
 * this file is the wrapper around the generator, and handles all the twitter related stuff
 */
var Twit = require('twit');
var fs  = require('fs');
var path = require('path');
var generator = require('./generator.js');
var secrets = require('./secrets.js');
var data = require('./data.js');

var Twitter = new Twit(secrets);

handleArguments();

/**
 * decide what to do based on what commands were passed in
 */
function handleArguments() {

	var count = 1,
		type = null;

	switch(process.argv[2]) {

		// generate some stuff
		case 'gen' :

			// how many?
			if(process.argv[3]) {
				count = parseInt(process.argv[3]);
			}

			// specific type?
			if(process.argv[4]) {
				type = 	process.argv[4];
			}

			// spit them out
			while(count--) {
				console.log( generator.generateSafe(type) );
			}

			break;

		// send a tweet
		case 'tweet':

			tweet();
			break;

		// listen for commands
		case 'monitor':

			monitor();
			break;

	}
}

/**
 * watch the gameideamachine user stream
 * look for tweets at it
 */
function monitor() {

	var stream = Twitter.stream('user');

	stream.on('tweet', function (tweet) {

		var message = tweet.text;
		var command = message.replace('@gameideamachine','').trim().toLowerCase();

		if(command === 'idea') {
			reply(tweet, generator.generateSafe(null, tweet.user.screen_name));
		} else if(data[command]) {
			reply(tweet, generator.generateSafe(command, tweet.user.screen_name));
		} else {
			// unknown request- log somewhere?
			return;
		}

	});
}

function reply(tweet, message) {

	var status = '@' + tweet.user.screen_name + ' ' + message;

	Twitter.post('statuses/update', {
		status: status,
		in_reply_to_status_id : tweet.id_str
	}, function(err, reply) {});
}

function tweet() {

	var file = path.resolve(__dirname, 'queue.txt');

	fs.readFile(file, function(err, contents) {

		var queue = contents.toString().split('\n');
		var status = queue.shift();

		if(!status) {
			status = generator.generateSafe();
		}

		Twitter.post('statuses/update', { status: status }, function(err, reply) {

			// drop any empty elements
			queue = queue.filter(function(e){ return e; });

			// add a replacement to the queue
			queue.push(generator.generateSafe());

			fs.writeFile(file, queue.join('\n'), function (err) { });

			if(err) { console.log(err); }

		});
	});
}
<commit_msg>added logging<commit_after>/**
 * Game Idea Machine
 * a twitter bot which tweets random game ideas
 * this file is the wrapper around the generator, and handles all the twitter related stuff
 */
var Twit = require('twit');
var fs  = require('fs');
var path = require('path');
var util = require('util');
var generator = require('./generator.js');
var secrets = require('./secrets.js');
var data = require('./data.js');

var Twitter = new Twit(secrets);

handleArguments();

/**
 * decide what to do based on what commands were passed in
 */
function handleArguments() {

	var count = 1,
		type = null;

	switch(process.argv[2]) {

		// generate some stuff
		case 'gen' :

			// how many?
			if(process.argv[3]) {
				count = parseInt(process.argv[3]);
			}

			// specific type?
			if(process.argv[4]) {
				type = 	process.argv[4];
			}

			// spit them out
			while(count--) {
				util.log( generator.generateSafe(type) );
			}

			break;

		// send a tweet
		case 'tweet':

			tweet();
			break;

		// listen for commands
		case 'monitor':

			monitor();
			break;

	}
}

/**
 * watch the gameideamachine user stream
 * look for tweets at it
 */
function monitor() {

	var stream = Twitter.stream('user');

	stream.on('tweet', function (tweet) {

		var message = tweet.text;
		var command = message.replace('@gameideamachine','').trim().toLowerCase();

		if(command === 'idea') {
			reply(tweet, generator.generateSafe(null, tweet.user.screen_name));
		} else if(data[command]) {
			reply(tweet, generator.generateSafe(command, tweet.user.screen_name));
		} else {
			util.log('unknown command', command);
			return;
		}

	});
}

function reply(tweet, message) {

	var status = '@' + tweet.user.screen_name + ' ' + message;

	Twitter.post('statuses/update', {
		status: status,
		in_reply_to_status_id : tweet.id_str
	}, function(err, reply) {
		if(err) { util.log(err); }
		else { util.log('reply sent to', tweet.user.screen_name); }
	});
}

function tweet() {

	var file = path.resolve(__dirname, 'queue.txt');

	fs.readFile(file, function(err, contents) {

		var queue = contents.toString().split('\n');
		var status = queue.shift();

		if(!status) {
			status = generator.generateSafe();
		}

		Twitter.post('statuses/update', { status: status }, function(err, reply) {

			// drop any empty elements
			queue = queue.filter(function(e){ return e; });

			// add a replacement to the queue
			queue.push(generator.generateSafe());

			fs.writeFile(file, queue.join('\n'), function (err) { });

			if(err) { util.log(err); }
			else { util.log('tweet sent'); }

		});
	});
}
<|endoftext|>


<commit_before>/*jslint browser: true, indent: 2, plusplus: true, sloppy: true, vars: true */
/*global
 tempura: false,
 TestCase: false,
 assertEquals: false,
 assertFalse: false,
 assertFunction: false,
 assertNotNull: false,
 assertNotSame: false,
 assertNotUndefined: false,
 assertNull: false,
 assertObject: false,
 assertSame: true,
 assertTrue: false,
 fail: false */
var testCase = TestCase;
testCase('core', {

  'setUp': function () {
    this.core = tempura.internal.core;
  },

  'test walk: it should accept a simple property name': function () {
    var obj = {
      name : 'hoge'
    };
    var context = this.core.createInitialContext(obj);
    var wrapper = this.core.walk('name', context);
    assertSame('hoge', wrapper.value);
    assertSame(context, wrapper.context);
  },

  'test walk: it should accept a navigation path': function () {
    var obj = {
      person: {
        name: 'hoge'
      }
    };
    var context = this.core.createInitialContext(obj);
    var wrapper = this.core.walk('person.name', context);
    assertSame('hoge', wrapper.value);
    assertNotNull(obj.person, wrapper.context.$this);
  },

  'test walk: it should accept unknown path': function () {
    var obj = {
      person: {
        name: 'hoge'
      }
    };
    var context = this.core.createInitialContext(obj);
    var wrapper = this.core.walk('person.unknown', context);
    assertSame(undefined, wrapper.value);
    assertNotNull(obj.person, wrapper.context.$this);
  },

  'test createContext: it should return input data when the data is a tempura context' : function () {
    var parent = {};
    var data = {};
    data[this.core.TEMPURA_CONTEXT_MARK] = true;
    assertSame(data, this.core.createContext(parent, data));
  },

  'test createContext: it should return a new context when the input data is a plain object' : function () {
    var parent = {};
    var data = {};
    var context;
    parent[this.core.TEMPURA_CONTEXT_MARK] = true;
    parent[this.core.TEMPURA_OPTIONS] = {};
    parent[this.core.ROOT_CONTEXT] = {};
    parent[this.core.PARENT_CONTEXT] = {};
    parent[this.core.THIS] = {};
    context = this.core.createContext(parent, data);
    assertTrue(context[this.core.TEMPURA_CONTEXT_MARK]);
    assertSame(parent[this.core.TEMPURA_OPTIONS], context[this.core.TEMPURA_OPTIONS]);
    assertSame(parent[this.core.ROOT_CONTEXT], context[this.core.ROOT_CONTEXT]);
    assertSame(parent, context[this.core.PARENT_CONTEXT]);
    assertSame(data, context[this.core.THIS]);
  },

  'tege getTagPair: it should return same object by default': function () {
    var context = this.core.createInitialContext({});
    var pair = this.core.getTagPair(context);
    var context2 = this.core.createInitialContext({});
    var pair2 = this.core.getTagPair(context2);
    assertSame('{{', pair.otag);
    assertSame('}}', pair.ctag);
    assertSame(pair, pair2);
  },

  'tege getTagPair: it should return same object for the otag/ctag pair': function () {
    var context = this.core.createInitialContext({});
    var pair = this.core.getTagPair(context);
    var context2 = this.core.createInitialContext({}, {otag: '[[', ctag: ']]'});
    var pair2 = this.core.getTagPair(context2);
    var context3 = this.core.createInitialContext({}, {otag: '[[', ctag: ']]'});
    var pair3 = this.core.getTagPair(context3);
    assertSame('{{', pair.otag);
    assertSame('}}', pair.ctag);
    assertNotSame(pair, pair2);
    assertSame('[[', pair.otag);
    assertSame(']]', pair.ctag);
    assertSame(pair2, pair3);
  },

  'test includes: it should return true when a directive is included': function () {
    var context = this.core.createInitialContext({name: 'hoge'});
    assertTrue(this.core.includes('#', '
{{#name}}
', context));
    assertFalse(this.core.includes('#', '
#name
', context));
  },

  'test createInitialContext': function () {
    var obj = {};
    var options = {};
    var context = this.core.createInitialContext(obj, options);
    assertTrue(context[this.core.TEMPURA_CONTEXT_MARK]);
    assertSame(options, context[this.core.TEMPURA_OPTIONS]);
    assertSame(context, context.$root);
    assertNull(context.$parent);
    assertSame(obj, context.$this);
  },

  'test applyPipe: it should use a context pipe, if the pipe exists': function () {
    var obj = {
      enclose: function (value) {
        return '$' + value + '$';
      }
    };
    var options = {
      pipes: {
        enclose: function (value) {
          return '[' + value + ']';
        }
      }
    };
    var context = this.core.createInitialContext(obj, options);
    var value = this.core.applyPipes('hoge', ['enclose'], context);
    assertSame('$hoge$', value);
  },

  'test applyPipes: it should use a context pipe, if the pipe exists: the pipe name can be path form': function () {
    var obj = {
      person: {
        age: 20,
        appendAge: function (value) {
          return value + this.age;
        }
      }
    };
    var context = this.core.createInitialContext(obj);
    var value = this.core.applyPipes('hoge', ['person.appendAge'], context);
    assertSame('hoge20', value);
  },

  'test applyPipes: it should use a option pipe, if the same name pipe does not in the context': function () {
    var obj = {
    };
    var options = {
      pipes: {
        enclose: function (value) {
          return '[' + value + ']';
        }
      }
    };
    var context = this.core.createInitialContext(obj, options);
    var value = this.core.applyPipes('hoge', ['enclose'], context);
    assertSame('[hoge]', value);
  },

  'test resolveValue: it should evaluate a string': function () {
    var obj = {
      person: {
        name: 'hoge'
      }
    };
    var context = this.core.createInitialContext(obj);
    var value = this.core.resolveValue('person.name', [], context);
    assertSame('hoge', value);
  },

  'test resolveValue: it should evaluate a number': function () {
    var obj = {
      person: {
        age: 20
      }
    };
    var context = this.core.createInitialContext(obj);
    var value = this.core.resolveValue('person.age', [], context);
    assertSame(20, value);
  },

  'test resolveValue: it should evaluate a function': function () {
    var obj = {
      person: {
        name: function () {
          return this.$root.start + 'hoge is ' + this.age + ' years old' + this.$root.end;
        },
        age: 20
      },
      start: '[',
      end: ']'
    };
    var context = this.core.createInitialContext(obj);
    var value = this.core.resolveValue('person.name', [], context);
    assertSame('[hoge is 20 years old]', value);
  },

  'test resolveValue: it should evaluate preRender': function () {
    var obj = {
      person: {
        name: 'hoge'
      },
      enclose: function (value, mark) {
        return mark + value + mark;
      },
      pipe1: function (value) {
        return this.enclose(value, '@');
      },
      pipe2: function (value) {
        return this.enclose(value, '#');
      },
      pipe3: function (value) {
        return this.enclose(value, '%');
      }
    };
    var options = {
      preRender: function (value, next) {
        value = next(value);
        return value + '!';
      }
    };
    var context = this.core.createInitialContext(obj, options);
    var value = this.core.resolveValue('person.name', ['pipe1', 'pipe2', 'pipe3'], context);
    assertSame('%#@hoge@#%!', value);
  },

  'test transformTags: it should resolve property references': function () {
    var obj = {
      name: 'hoge',
      age: 20
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformTags('{{name}} is {{age}} years old.', context);
    assertSame('hoge is 20 years old.', result);
  },

  'test transformTags: it should apply pipes after resolving property reference': function () {
    var obj = {
      name: 'hoge',
      age: 20,
      double: function (value) {
        return value * 2;
      }
    };
    var options = {
      pipes: {
        enclose: function (value) {
          return '[' + value + ']';
        }
      }
    };
    var context = this.core.createInitialContext(obj, options);
    var result = this.core.transformTags('{{name|enclose}} is {{age|double|enclose}} years old.', context);
    assertSame('[hoge] is [40] years old.', result);
  },

  'test transformSection: it should return false if the input template does not contain "{{#" or "{{^"': function () {
    var obj = {
      name: 'hoge',
      age: 20
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('{{name}}', context);
    assertFalse(result);
  },

  'test transformSection: it should resolve context specific properties': function () {
    var obj = {
      rootName: 'aaa',
      parent: {
        parentName: 'bbb',
        child: {
          childName: 'ccc'
        }
      }
    };
    var context = this.core.createInitialContext(obj);
    var template = [
      '{{$root.rootName}},{{$parent.rootName}},{{$this.rootName}},{{rootName}}|',
      '{{#parent}}{{$root.rootName}},{{$parent.rootName}},{{$this.parentName}},{{parentName}}|',
      '{{#child}}{{$root.rootName}},{{$parent.parentName}},{{$this.childName}},{{childName}}{{/child}}{{/parent}}'
    ].join('');
    var result = this.core.transformSection(template, context);
    assertSame('aaa,,aaa,aaa|aaa,aaa,bbb,bbb|aaa,bbb,ccc,ccc', result);
  },

  'test transformSection: it should iterate array of object': function () {
    var obj = {
      people: [{
        name: 'aaa',
        age: 1
      }, {
        name: 'bbb',
        age: 2
      }]
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('[ {{#people}}{{name}} is {{age}} years old.\n{{/people}} ]', context);
    assertSame('[ aaa is 1 years old.\nbbb is 2 years old.\n ]', result);
  },

  'test transformSection: it should iterate array of string': function () {
    var obj = {
      people: [
        'aaa',
        'bbb'
      ]
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('[ {{#people}}{{$this}}\n{{/people}} ]', context);
    assertSame('[ aaa\nbbb\n ]', result);
  },

  'test transformSection: it should invoke function and if the result is true, it should handle content': function () {
    var obj = {
      value: 'hoge',
      isOk: function () {
        return true;
      }
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('[ {{#isOk}}{{value}}{{/isOk}} ]', context);
    assertSame('[ hoge ]', result);
  },

  'test transformSection: it should invoke function and if the result is false, it should ignore content': function () {
    var obj = {
      value: 'hoge',
      isOk: function () {
        return false;
      }
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('[ {{#isOk}}{{value}}{{/isOk}} ]', context);
    assertSame('[  ]', result);
  },

  'test transformSection: it should dereference object': function () {
    var obj = {
      person: {
        name: 'aaa',
        age: 1
      }
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('[ {{#person}}{{name}} is {{age}} years old.{{/person}} ]', context);
    assertSame('[ aaa is 1 years old. ]', result);
  },

  'test transformSection: it should evaluate boolean value as condition to handle content': function () {
    var obj = {
      value: true
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('[ {{#value}}aaa{{/value}}{{^value}}bbb{{/value}} ]', context);
    assertSame('[ aaa ]', result);
  },

  'test transform: it should handle a template contains tags': function () {
    var obj = {
      name: 'hoge',
      age: 20
    };
    var result = this.core.transform('{{name}} is {{age}} years old.', obj);
    assertSame('hoge is 20 years old.', result);
  },

  'test transform: it should handle a template contains sections': function () {
    var obj = {
      person: {
        name: 'aaa',
        age: 1
      },
      address: {
        street: 'bbb'
      }
    };
    var context = this.core.createInitialContext(obj);
    var template = '[ {{#person}}{{name}} is {{age}} years old.{{/person}} {{#address}}street is {{street}}.{{/address}} ]';
    var result = this.core.transform(template, context);
    assertSame('[ aaa is 1 years old. street is bbb. ]', result);
  },

  'test toHtml: it should encode a value if the value is enclosed with "{{" and "}}"': function () {
    var obj = { str: '', num: 1, func : function () { return ''; } };
    var result = this.core.toHtml('{{str}},{{num}},{{func}}', obj);
    assertSame('<a>,1,<b>', result);
  },

  'test toHtml: it should not encode value if the value is enclosed with "{{{" and "}}}"': function () {
    var obj = { str: '', num: 1, func : function () { return ''; } };
    var result = this.core.toHtml('{{{str}}},{{{num}}},{{{func}}}', obj);
    assertSame(',1,', result);
  },

  'test prepare: it should return a object': function () {
    var template = this.core.prepare('');
    assertObject(template);
    assertFunction(template.render);
  }

});<commit_msg>added test.<commit_after>/*jslint browser: true, indent: 2, plusplus: true, sloppy: true, vars: true */
/*global
 tempura: false,
 TestCase: false,
 assertEquals: false,
 assertFalse: false,
 assertFunction: false,
 assertNotNull: false,
 assertNotSame: false,
 assertNotUndefined: false,
 assertNull: false,
 assertObject: false,
 assertSame: true,
 assertTrue: false,
 fail: false */
var testCase = TestCase;
testCase('core', {

  'setUp': function () {
    this.core = tempura.internal.core;
  },

  'getTagPair: it should return default pair': function () {
    var context = this.core.createInitialContext({});
    var pair = this.core.getTagPair();
    assertSame('{{', pair.otag);
    assertSame('}}', pair.ctag);
  },

  'getTagPair: it should reflect option settings': function () {
    var context = this.core.createInitialContext({}, {otag: '[[', ctag: ']]'});
    var pair = this.core.getTagPair();
    assertSame('[[', pair.otag);
    assertSame(']]', pair.ctag);
  },

  'test walk: it should accept a simple property name': function () {
    var obj = {
      name : 'hoge'
    };
    var context = this.core.createInitialContext(obj);
    var wrapper = this.core.walk('name', context);
    assertSame('hoge', wrapper.value);
    assertSame(context, wrapper.context);
  },

  'test walk: it should accept a navigation path': function () {
    var obj = {
      person: {
        name: 'hoge'
      }
    };
    var context = this.core.createInitialContext(obj);
    var wrapper = this.core.walk('person.name', context);
    assertSame('hoge', wrapper.value);
    assertNotNull(obj.person, wrapper.context.$this);
  },

  'test walk: it should accept unknown path': function () {
    var obj = {
      person: {
        name: 'hoge'
      }
    };
    var context = this.core.createInitialContext(obj);
    var wrapper = this.core.walk('person.unknown', context);
    assertSame(undefined, wrapper.value);
    assertNotNull(obj.person, wrapper.context.$this);
  },

  'test createContext: it should return input data when the data is a tempura context' : function () {
    var parent = {};
    var data = {};
    data[this.core.TEMPURA_CONTEXT_MARK] = true;
    assertSame(data, this.core.createContext(parent, data));
  },

  'test createContext: it should return a new context when the input data is a plain object' : function () {
    var parent = {};
    var data = {};
    var context;
    parent[this.core.TEMPURA_CONTEXT_MARK] = true;
    parent[this.core.TEMPURA_OPTIONS] = {};
    parent[this.core.ROOT_CONTEXT] = {};
    parent[this.core.PARENT_CONTEXT] = {};
    parent[this.core.THIS] = {};
    context = this.core.createContext(parent, data);
    assertTrue(context[this.core.TEMPURA_CONTEXT_MARK]);
    assertSame(parent[this.core.TEMPURA_OPTIONS], context[this.core.TEMPURA_OPTIONS]);
    assertSame(parent[this.core.ROOT_CONTEXT], context[this.core.ROOT_CONTEXT]);
    assertSame(parent, context[this.core.PARENT_CONTEXT]);
    assertSame(data, context[this.core.THIS]);
  },

  'tege getTagPair: it should return same object by default': function () {
    var context = this.core.createInitialContext({});
    var pair = this.core.getTagPair(context);
    var context2 = this.core.createInitialContext({});
    var pair2 = this.core.getTagPair(context2);
    assertSame('{{', pair.otag);
    assertSame('}}', pair.ctag);
    assertSame(pair, pair2);
  },

  'tege getTagPair: it should return same object for the otag/ctag pair': function () {
    var context = this.core.createInitialContext({});
    var pair = this.core.getTagPair(context);
    var context2 = this.core.createInitialContext({}, {otag: '[[', ctag: ']]'});
    var pair2 = this.core.getTagPair(context2);
    var context3 = this.core.createInitialContext({}, {otag: '[[', ctag: ']]'});
    var pair3 = this.core.getTagPair(context3);
    assertSame('{{', pair.otag);
    assertSame('}}', pair.ctag);
    assertNotSame(pair, pair2);
    assertSame('[[', pair.otag);
    assertSame(']]', pair.ctag);
    assertSame(pair2, pair3);
  },

  'test includes: it should return true when a directive is included': function () {
    var context = this.core.createInitialContext({name: 'hoge'});
    assertTrue(this.core.includes('#', '
{{#name}}
', context));
    assertFalse(this.core.includes('#', '
#name
', context));
  },

  'test createInitialContext': function () {
    var obj = {};
    var options = {};
    var context = this.core.createInitialContext(obj, options);
    assertTrue(context[this.core.TEMPURA_CONTEXT_MARK]);
    assertSame(options, context[this.core.TEMPURA_OPTIONS]);
    assertSame(context, context.$root);
    assertNull(context.$parent);
    assertSame(obj, context.$this);
  },

  'test applyPipe: it should use a context pipe, if the pipe exists': function () {
    var obj = {
      enclose: function (value) {
        return '$' + value + '$';
      }
    };
    var options = {
      pipes: {
        enclose: function (value) {
          return '[' + value + ']';
        }
      }
    };
    var context = this.core.createInitialContext(obj, options);
    var value = this.core.applyPipes('hoge', ['enclose'], context);
    assertSame('$hoge$', value);
  },

  'test applyPipes: it should use a context pipe, if the pipe exists: the pipe name can be path form': function () {
    var obj = {
      person: {
        age: 20,
        appendAge: function (value) {
          return value + this.age;
        }
      }
    };
    var context = this.core.createInitialContext(obj);
    var value = this.core.applyPipes('hoge', ['person.appendAge'], context);
    assertSame('hoge20', value);
  },

  'test applyPipes: it should use a option pipe, if the same name pipe does not in the context': function () {
    var obj = {
    };
    var options = {
      pipes: {
        enclose: function (value) {
          return '[' + value + ']';
        }
      }
    };
    var context = this.core.createInitialContext(obj, options);
    var value = this.core.applyPipes('hoge', ['enclose'], context);
    assertSame('[hoge]', value);
  },

  'test resolveValue: it should evaluate a string': function () {
    var obj = {
      person: {
        name: 'hoge'
      }
    };
    var context = this.core.createInitialContext(obj);
    var value = this.core.resolveValue('person.name', [], context);
    assertSame('hoge', value);
  },

  'test resolveValue: it should evaluate a number': function () {
    var obj = {
      person: {
        age: 20
      }
    };
    var context = this.core.createInitialContext(obj);
    var value = this.core.resolveValue('person.age', [], context);
    assertSame(20, value);
  },

  'test resolveValue: it should evaluate a function': function () {
    var obj = {
      person: {
        name: function () {
          return this.$root.start + 'hoge is ' + this.age + ' years old' + this.$root.end;
        },
        age: 20
      },
      start: '[',
      end: ']'
    };
    var context = this.core.createInitialContext(obj);
    var value = this.core.resolveValue('person.name', [], context);
    assertSame('[hoge is 20 years old]', value);
  },

  'test resolveValue: it should evaluate preRender': function () {
    var obj = {
      person: {
        name: 'hoge'
      },
      enclose: function (value, mark) {
        return mark + value + mark;
      },
      pipe1: function (value) {
        return this.enclose(value, '@');
      },
      pipe2: function (value) {
        return this.enclose(value, '#');
      },
      pipe3: function (value) {
        return this.enclose(value, '%');
      }
    };
    var options = {
      preRender: function (value, next) {
        value = next(value);
        return value + '!';
      }
    };
    var context = this.core.createInitialContext(obj, options);
    var value = this.core.resolveValue('person.name', ['pipe1', 'pipe2', 'pipe3'], context);
    assertSame('%#@hoge@#%!', value);
  },

  'test transformTags: it should resolve property references': function () {
    var obj = {
      name: 'hoge',
      age: 20
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformTags('{{name}} is {{age}} years old.', context);
    assertSame('hoge is 20 years old.', result);
  },

  'test transformTags: it should apply pipes after resolving property reference': function () {
    var obj = {
      name: 'hoge',
      age: 20,
      double: function (value) {
        return value * 2;
      }
    };
    var options = {
      pipes: {
        enclose: function (value) {
          return '[' + value + ']';
        }
      }
    };
    var context = this.core.createInitialContext(obj, options);
    var result = this.core.transformTags('{{name|enclose}} is {{age|double|enclose}} years old.', context);
    assertSame('[hoge] is [40] years old.', result);
  },

  'test transformSection: it should return false if the input template does not contain "{{#" or "{{^"': function () {
    var obj = {
      name: 'hoge',
      age: 20
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('{{name}}', context);
    assertFalse(result);
  },

  'test transformSection: it should resolve context specific properties': function () {
    var obj = {
      rootName: 'aaa',
      parent: {
        parentName: 'bbb',
        child: {
          childName: 'ccc'
        }
      }
    };
    var context = this.core.createInitialContext(obj);
    var template = [
      '{{$root.rootName}},{{$parent.rootName}},{{$this.rootName}},{{rootName}}|',
      '{{#parent}}{{$root.rootName}},{{$parent.rootName}},{{$this.parentName}},{{parentName}}|',
      '{{#child}}{{$root.rootName}},{{$parent.parentName}},{{$this.childName}},{{childName}}{{/child}}{{/parent}}'
    ].join('');
    var result = this.core.transformSection(template, context);
    assertSame('aaa,,aaa,aaa|aaa,aaa,bbb,bbb|aaa,bbb,ccc,ccc', result);
  },

  'test transformSection: it should iterate array of object': function () {
    var obj = {
      people: [{
        name: 'aaa',
        age: 1
      }, {
        name: 'bbb',
        age: 2
      }]
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('[ {{#people}}{{name}} is {{age}} years old.\n{{/people}} ]', context);
    assertSame('[ aaa is 1 years old.\nbbb is 2 years old.\n ]', result);
  },

  'test transformSection: it should iterate array of string': function () {
    var obj = {
      people: [
        'aaa',
        'bbb'
      ]
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('[ {{#people}}{{$this}}\n{{/people}} ]', context);
    assertSame('[ aaa\nbbb\n ]', result);
  },

  'test transformSection: it should invoke function and if the result is true, it should handle content': function () {
    var obj = {
      value: 'hoge',
      isOk: function () {
        return true;
      }
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('[ {{#isOk}}{{value}}{{/isOk}} ]', context);
    assertSame('[ hoge ]', result);
  },

  'test transformSection: it should invoke function and if the result is false, it should ignore content': function () {
    var obj = {
      value: 'hoge',
      isOk: function () {
        return false;
      }
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('[ {{#isOk}}{{value}}{{/isOk}} ]', context);
    assertSame('[  ]', result);
  },

  'test transformSection: it should dereference object': function () {
    var obj = {
      person: {
        name: 'aaa',
        age: 1
      }
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('[ {{#person}}{{name}} is {{age}} years old.{{/person}} ]', context);
    assertSame('[ aaa is 1 years old. ]', result);
  },

  'test transformSection: it should evaluate boolean value as condition to handle content': function () {
    var obj = {
      value: true
    };
    var context = this.core.createInitialContext(obj);
    var result = this.core.transformSection('[ {{#value}}aaa{{/value}}{{^value}}bbb{{/value}} ]', context);
    assertSame('[ aaa ]', result);
  },

  'test transform: it should handle a template contains tags': function () {
    var obj = {
      name: 'hoge',
      age: 20
    };
    var result = this.core.transform('{{name}} is {{age}} years old.', obj);
    assertSame('hoge is 20 years old.', result);
  },

  'test transform: it should handle a template contains sections': function () {
    var obj = {
      person: {
        name: 'aaa',
        age: 1
      },
      address: {
        street: 'bbb'
      }
    };
    var context = this.core.createInitialContext(obj);
    var template = '[ {{#person}}{{name}} is {{age}} years old.{{/person}} {{#address}}street is {{street}}.{{/address}} ]';
    var result = this.core.transform(template, context);
    assertSame('[ aaa is 1 years old. street is bbb. ]', result);
  },

  'test toHtml: it should encode a value if the value is enclosed with "{{" and "}}"': function () {
    var obj = { str: '', num: 1, func : function () { return ''; } };
    var result = this.core.toHtml('{{str}},{{num}},{{func}}', obj);
    assertSame('<a>,1,<b>', result);
  },

  'test toHtml: it should not encode value if the value is enclosed with "{{{" and "}}}"': function () {
    var obj = { str: '', num: 1, func : function () { return ''; } };
    var result = this.core.toHtml('{{{str}}},{{{num}}},{{{func}}}', obj);
    assertSame(',1,', result);
  },

  'test prepare: it should return a object': function () {
    var template = this.core.prepare('');
    assertObject(template);
    assertFunction(template.render);
  }

});<|endoftext|>


<commit_before>var tape = require('tape')
var hypercore = require('./helpers/create')
var copy = require('./helpers/copy')

tape('append one', function (t) {
  var feed = hypercore().createFeed()

  feed.append('hello', function () {
    t.same(feed.has(0), true, 'has first')
    feed.get(0, function (err, data) {
      t.error(err, 'no error')
      t.same(data, Buffer('hello'), 'first is hello')
      t.end()
    })
  })
})

tape('append, close, resume', function (t) {
  var core = hypercore()
  var feed = core.createFeed()

  feed.append('hello')
  feed.close(function () {
    var feed1 = core.createFeed(feed.key)
    feed1.append('world')
    feed1.flush(function () {
      t.same(feed1.has(0), true, 'has first')
      t.same(feed1.has(1), true, 'has second')
      feed1.get(0, function (err, data) {
        t.error(err, 'no error')
        t.same(data, Buffer('hello'), 'was hello')
        feed1.get(1, function (err, data) {
          t.error(err, 'no error')
          t.same(data, Buffer('world'), 'was world')
          t.end()
        })
      })
    })
  })
})

tape('non-live append and finalize', function (t) {
  var feed = hypercore().createFeed({live: false})
  feed.append('hello')
  feed.finalize(function () {
    t.same(feed.key, Buffer('3ae3cbe25fbd381ae3137f5286ac7eb8fcec7255e8eef864e0aa0e605220a429', 'hex'))
    t.end()
  })
})

tape('non-live finalize empty', function (t) {
  var feed = hypercore().createFeed({live: false})
  feed.finalize(function () {
    t.same(feed.key, null)
    t.end()
  })
})

tape('non-live replicate without digest', function (t) {
  var feed = hypercore().createFeed({live: false})
  feed.append(['a', 'b', 'c'])
  feed.finalize(function () {
    var clone = hypercore().createFeed(feed.key)
    var missing = [0, 1, 2]

    loop()

    function loop () {
      if (!missing.length) return t.end()
      var next = missing.shift()
      feed.proof(next, function (err, proof) {
        t.error(err, 'no proof error')
        feed.get(next, function (err, data) {
          t.error(err, 'no get error')
          clone.put(next, data, proof, function (err) {
            t.error(err, 'no put error')
            t.same(clone.has(next), true, 'clone has ' + next)
            loop()
          })
        })
      })
    }
  })
})

tape('non-live replicate with digest', function (t) {
  var feed = hypercore().createFeed({live: false})
  feed.append(['a', 'b', 'c'])
  feed.finalize(function () {
    var clone = hypercore().createFeed(feed.key)
    var missing = [0, 1, 2]

    loop()

    function loop () {
      if (!missing.length) return t.end()
      var next = missing.shift()
      feed.proof(next, {digest: clone.digest(next)}, function (err, proof) {
        t.error(err, 'no proof error')
        if (next) t.same(proof.nodes.length, 0, 'no nodes needed')
        feed.get(next, function (err, data) {
          t.error(err, 'no get error')
          clone.put(next, data, proof, function (err) {
            t.error(err, 'no put error')
            t.same(clone.has(next), true, 'clone has ' + next)
            loop()
          })
        })
      })
    }
  })
})

tape('invalid non-live replicate with digest', function (t) {
  t.plan(3)

  var feed = hypercore().createFeed({live: false})
  feed.append(['a', 'b', 'c'])
  feed.finalize(function () {
    var key = Buffer('00000000000000000000000000000000')
    var clone = hypercore().createFeed(key)

    copy(0, feed, clone, function (err) {
      t.ok(err, 'should error')
    })
    copy(1, feed, clone, function (err) {
      t.ok(err, 'should error')
    })
    copy(2, feed, clone, function (err) {
      t.ok(err, 'should error')
    })
  })
})

tape('replicate without digest', function (t) {
  var feed = hypercore().createFeed()
  var clone = hypercore().createFeed(feed.key)
  feed.append(['a', 'b', 'c'], function () {
    var missing = [0, 1, 2]

    loop()

    function loop () {
      if (!missing.length) return t.end()
      var next = missing.shift()
      feed.proof(next, function (err, proof) {
        t.ok(proof.signature, 'signed')
        t.error(err, 'no proof error')
        feed.get(next, function (err, data) {
          t.error(err, 'no get error')
          clone.put(next, data, proof, function (err) {
            t.error(err, 'no put error')
            t.same(clone.has(next), true, 'clone has ' + next)
            loop()
          })
        })
      })
    }
  })
})

tape('replicate with digest', function (t) {
  var feed = hypercore().createFeed()
  var clone = hypercore().createFeed(feed.key)
  feed.append(['a', 'b', 'c'], function () {
    var missing = [0, 1, 2]

    loop()

    function loop () {
      if (!missing.length) return t.end()
      var next = missing.shift()
      feed.proof(next, {digest: clone.digest(next)}, function (err, proof) {
        t.same(!!proof.signature, next === 0, 'only first one is signed')
        t.error(err, 'no proof error')
        if (next) t.same(proof.nodes.length, 0, 'no nodes needed')
        feed.get(next, function (err, data) {
          t.error(err, 'no get error')
          clone.put(next, data, proof, function (err) {
            t.error(err, 'no put error')
            t.same(clone.has(next), true, 'clone has ' + next)
            loop()
          })
        })
      })
    }
  })
})

tape('invalid replicate with digest', function (t) {
  t.plan(3)

  var feed = hypercore().createFeed()
  feed.append(['a', 'b', 'c'])
  feed.finalize(function () {
    var key = Buffer('00000000000000000000000000000000')
    var clone = hypercore().createFeed(key)

    copy(0, feed, clone, function (err) {
      t.ok(err, 'should error')
    })
    copy(1, feed, clone, function (err) {
      t.ok(err, 'should error')
    })
    copy(2, feed, clone, function (err) {
      t.ok(err, 'should error')
    })
  })
})

tape('replicate, append, replicate', function (t) {
  var feed = hypercore().createFeed()
  var clone1 = hypercore().createFeed(feed.key)
  var clone2 = hypercore().createFeed(feed.key)

  feed.append(['a', 'b', 'c'], function () {
    copy(1, feed, clone1, function (err) {
      t.error(err, 'no copy error')
      t.ok(clone1.has(1), 'has 1')
      feed.append(['d', 'e', 'f', 'g', 'h', 'i', 'j', 'k'], function () {
        copy(9, feed, clone1, function (err) {
          t.error(err, 'no copy error')
          t.ok(clone1.has(9), 'has 9')
          copy(1, clone1, clone2, function (err) {
            t.error(err, 'no copy error')
            t.ok(clone2.has(1), 'has 1')
            copy(9, clone1, clone2, function (err) {
              t.error(err, 'no copy error')
              t.ok(clone2.has(9), 'has 9')
              t.end()
            })
          })
        })
      })
    })
  })
})

tape.skip('append and get empty value', function (t) {
  var feed = hypercore().createFeed()

  feed.append(Buffer(0), function (err) {
    t.error(err, 'no append error')
    feed.get(0, function (err, value) {
      t.error(err, 'no get error')
      t.same(value, Buffer(0), 'empty buffer')
      t.end()
    })
  })
})

// tests below was generated by a randomizer triggering different replication edge cases

tape('chaos monkey generated #1', function (t) {
  var ops = []
  ops.push({type: 'append', value: '998'})
  ops.push({type: 'copy', block: 0, from: 'feed', to: 'clone1'})
  runOps(t, ops)
})

tape('chaos monkey generated #2', function (t) {
  var ops = []
  ops.push({type: 'append', value: '993'})
  ops.push({type: 'append', value: '992'})
  ops.push({type: 'append', value: '991'})
  ops.push({type: 'copy', block: 0, from: 'feed', to: 'clone1'})
  ops.push({type: 'append', value: '984'})
  ops.push({type: 'copy', block: 1, from: 'feed', to: 'clone1'})
  ops.push({type: 'append', value: '982'})
  ops.push({type: 'copy', block: 0, from: 'clone1', to: 'clone2'})
  ops.push({type: 'copy', block: 3, from: 'feed', to: 'clone1'})
  runOps(t, ops)
})

tape('chaos monkey generated #3', function (t) {
  var ops = []
  ops.push({type: 'append', value: '996'})
  ops.push({type: 'append', value: '994'})
  ops.push({type: 'copy', block: 1, from: 'feed', to: 'clone1'})
  ops.push({type: 'copy', block: 1, from: 'clone1', to: 'clone2'})
  ops.push({type: 'append', value: '991'})
  ops.push({type: 'append', value: '990'})
  ops.push({type: 'append', value: '988'})
  ops.push({type: 'append', value: '985'})
  ops.push({type: 'copy', block: 5, from: 'feed', to: 'clone1'})
  ops.push({type: 'copy', block: 5, from: 'clone1', to: 'clone2'})
  ops.push({type: 'append', value: '981'})
  ops.push({type: 'append', value: '980'})
  ops.push({type: 'append', value: '976'})
  ops.push({type: 'append', value: '974'})
  ops.push({type: 'append', value: '972'})
  ops.push({type: 'append', value: '971'})
  ops.push({type: 'append', value: '969'})
  ops.push({type: 'copy', block: 8, from: 'feed', to: 'clone1'})
  ops.push({type: 'copy', block: 8, from: 'clone1', to: 'clone2'})
  ops.push({type: 'append', value: '965'})
  ops.push({type: 'copy', block: 6, from: 'feed', to: 'clone1'})
  ops.push({type: 'copy', block: 3, from: 'feed', to: 'clone1'})
  ops.push({type: 'append', value: '961'})
  ops.push({type: 'copy', block: 6, from: 'clone1', to: 'clone2'})
  ops.push({type: 'append', value: '957'})
  ops.push({type: 'append', value: '956'})
  ops.push({type: 'copy', block: 3, from: 'clone1', to: 'clone2'})
  ops.push({type: 'append', value: '953'})
  ops.push({type: 'append', value: '952'})
  ops.push({type: 'append', value: '951'})
  ops.push({type: 'append', value: '950'})
  ops.push({type: 'copy', block: 17, from: 'feed', to: 'clone1'})
  ops.push({type: 'append', value: '947'})
  ops.push({type: 'append', value: '946'})
  ops.push({type: 'copy', block: 18, from: 'feed', to: 'clone1'})
  ops.push({type: 'append', value: '944'})
  ops.push({type: 'copy', block: 22, from: 'feed', to: 'clone1'})
  runOps(t, ops)
})

tape('chaos monkey randomized', function (t) {
  var feed = hypercore().createFeed()
  var clone1 = hypercore().createFeed(feed.key)
  var clone2 = hypercore().createFeed(feed.key)
  var names = ['feed', 'clone1', 'clone2']
  var runs = 500

  loop()

  function loop () {
    if (--runs === 0) return t.end()
    if (Math.random() < 0.3) {
      return feed.append('' + runs, loop)
    }
    if (Math.random() < 0.5) return process.nextTick(loop)

    var from = [feed, clone1, clone2][(Math.random() * 3) | 0]
    var to = null
    if (from === clone1) to = clone2
    else if (from === clone2) to = clone1
    else to = [clone1, clone1][(Math.random() * 2) | 0]

    var blk = -1
    var seen = 0

    for (var i = 0; i < from.bitfield.length; i++) {
      if (!from.has(i) || to.has(i)) continue
      if (Math.random() < 1 / ++seen) blk = i
    }

    if (blk === -1) return process.nextTick(loop)

    copy(blk, from, to, function (err) {
      if (err) {
        t.fail('failed to copy ' + blk + ' from ' + name(from) + ' to ' + name(to))
        t.end()
        return
      }

      t.pass('copied ' + blk + ' from ' + name(from) + ' to ' + name(to))
      loop()
    })
  }

  function name (f) {
    return names[[feed, clone1, clone2].indexOf(f)]
  }
})

function runOps (t, ops) {
  var feed = hypercore().createFeed()
  var clone1 = hypercore().createFeed(feed.key)
  var clone2 = hypercore().createFeed(feed.key)

  loop()

  function get (name) {
    if (name === 'feed') return feed
    if (name === 'clone1') return clone1
    return clone2
  }

  function loop () {
    var next = ops.shift()
    if (!next) {
      t.end()
      return
    }
    if (next.type === 'append') {
      feed.append(next.value, loop)
      return
    }
    if (next.type === 'copy') {
      copy(next.block, get(next.from), get(next.to), function (err) {
        if (err) {
          t.fail('failed to copy ' + next.block + ' from ' + next.from + ' to ' + next.to)
          t.end()
          return
        }
        t.pass('copied ' + next.block + ' from ' + next.from + ' to ' + next.to)
        loop()
      })
      return
    }
  }
}
<commit_msg>enable empty test<commit_after>var tape = require('tape')
var hypercore = require('./helpers/create')
var copy = require('./helpers/copy')

tape('append one', function (t) {
  var feed = hypercore().createFeed()

  feed.append('hello', function () {
    t.same(feed.has(0), true, 'has first')
    feed.get(0, function (err, data) {
      t.error(err, 'no error')
      t.same(data, Buffer('hello'), 'first is hello')
      t.end()
    })
  })
})

tape('append, close, resume', function (t) {
  var core = hypercore()
  var feed = core.createFeed()

  feed.append('hello')
  feed.close(function () {
    var feed1 = core.createFeed(feed.key)
    feed1.append('world')
    feed1.flush(function () {
      t.same(feed1.has(0), true, 'has first')
      t.same(feed1.has(1), true, 'has second')
      feed1.get(0, function (err, data) {
        t.error(err, 'no error')
        t.same(data, Buffer('hello'), 'was hello')
        feed1.get(1, function (err, data) {
          t.error(err, 'no error')
          t.same(data, Buffer('world'), 'was world')
          t.end()
        })
      })
    })
  })
})

tape('non-live append and finalize', function (t) {
  var feed = hypercore().createFeed({live: false})
  feed.append('hello')
  feed.finalize(function () {
    t.same(feed.key, Buffer('3ae3cbe25fbd381ae3137f5286ac7eb8fcec7255e8eef864e0aa0e605220a429', 'hex'))
    t.end()
  })
})

tape('non-live finalize empty', function (t) {
  var feed = hypercore().createFeed({live: false})
  feed.finalize(function () {
    t.same(feed.key, null)
    t.end()
  })
})

tape('non-live replicate without digest', function (t) {
  var feed = hypercore().createFeed({live: false})
  feed.append(['a', 'b', 'c'])
  feed.finalize(function () {
    var clone = hypercore().createFeed(feed.key)
    var missing = [0, 1, 2]

    loop()

    function loop () {
      if (!missing.length) return t.end()
      var next = missing.shift()
      feed.proof(next, function (err, proof) {
        t.error(err, 'no proof error')
        feed.get(next, function (err, data) {
          t.error(err, 'no get error')
          clone.put(next, data, proof, function (err) {
            t.error(err, 'no put error')
            t.same(clone.has(next), true, 'clone has ' + next)
            loop()
          })
        })
      })
    }
  })
})

tape('non-live replicate with digest', function (t) {
  var feed = hypercore().createFeed({live: false})
  feed.append(['a', 'b', 'c'])
  feed.finalize(function () {
    var clone = hypercore().createFeed(feed.key)
    var missing = [0, 1, 2]

    loop()

    function loop () {
      if (!missing.length) return t.end()
      var next = missing.shift()
      feed.proof(next, {digest: clone.digest(next)}, function (err, proof) {
        t.error(err, 'no proof error')
        if (next) t.same(proof.nodes.length, 0, 'no nodes needed')
        feed.get(next, function (err, data) {
          t.error(err, 'no get error')
          clone.put(next, data, proof, function (err) {
            t.error(err, 'no put error')
            t.same(clone.has(next), true, 'clone has ' + next)
            loop()
          })
        })
      })
    }
  })
})

tape('invalid non-live replicate with digest', function (t) {
  t.plan(3)

  var feed = hypercore().createFeed({live: false})
  feed.append(['a', 'b', 'c'])
  feed.finalize(function () {
    var key = Buffer('00000000000000000000000000000000')
    var clone = hypercore().createFeed(key)

    copy(0, feed, clone, function (err) {
      t.ok(err, 'should error')
    })
    copy(1, feed, clone, function (err) {
      t.ok(err, 'should error')
    })
    copy(2, feed, clone, function (err) {
      t.ok(err, 'should error')
    })
  })
})

tape('replicate without digest', function (t) {
  var feed = hypercore().createFeed()
  var clone = hypercore().createFeed(feed.key)
  feed.append(['a', 'b', 'c'], function () {
    var missing = [0, 1, 2]

    loop()

    function loop () {
      if (!missing.length) return t.end()
      var next = missing.shift()
      feed.proof(next, function (err, proof) {
        t.ok(proof.signature, 'signed')
        t.error(err, 'no proof error')
        feed.get(next, function (err, data) {
          t.error(err, 'no get error')
          clone.put(next, data, proof, function (err) {
            t.error(err, 'no put error')
            t.same(clone.has(next), true, 'clone has ' + next)
            loop()
          })
        })
      })
    }
  })
})

tape('replicate with digest', function (t) {
  var feed = hypercore().createFeed()
  var clone = hypercore().createFeed(feed.key)
  feed.append(['a', 'b', 'c'], function () {
    var missing = [0, 1, 2]

    loop()

    function loop () {
      if (!missing.length) return t.end()
      var next = missing.shift()
      feed.proof(next, {digest: clone.digest(next)}, function (err, proof) {
        t.same(!!proof.signature, next === 0, 'only first one is signed')
        t.error(err, 'no proof error')
        if (next) t.same(proof.nodes.length, 0, 'no nodes needed')
        feed.get(next, function (err, data) {
          t.error(err, 'no get error')
          clone.put(next, data, proof, function (err) {
            t.error(err, 'no put error')
            t.same(clone.has(next), true, 'clone has ' + next)
            loop()
          })
        })
      })
    }
  })
})

tape('invalid replicate with digest', function (t) {
  t.plan(3)

  var feed = hypercore().createFeed()
  feed.append(['a', 'b', 'c'])
  feed.finalize(function () {
    var key = Buffer('00000000000000000000000000000000')
    var clone = hypercore().createFeed(key)

    copy(0, feed, clone, function (err) {
      t.ok(err, 'should error')
    })
    copy(1, feed, clone, function (err) {
      t.ok(err, 'should error')
    })
    copy(2, feed, clone, function (err) {
      t.ok(err, 'should error')
    })
  })
})

tape('replicate, append, replicate', function (t) {
  var feed = hypercore().createFeed()
  var clone1 = hypercore().createFeed(feed.key)
  var clone2 = hypercore().createFeed(feed.key)

  feed.append(['a', 'b', 'c'], function () {
    copy(1, feed, clone1, function (err) {
      t.error(err, 'no copy error')
      t.ok(clone1.has(1), 'has 1')
      feed.append(['d', 'e', 'f', 'g', 'h', 'i', 'j', 'k'], function () {
        copy(9, feed, clone1, function (err) {
          t.error(err, 'no copy error')
          t.ok(clone1.has(9), 'has 9')
          copy(1, clone1, clone2, function (err) {
            t.error(err, 'no copy error')
            t.ok(clone2.has(1), 'has 1')
            copy(9, clone1, clone2, function (err) {
              t.error(err, 'no copy error')
              t.ok(clone2.has(9), 'has 9')
              t.end()
            })
          })
        })
      })
    })
  })
})

tape('append and get empty value', function (t) {
  var feed = hypercore().createFeed()

  feed.append(Buffer(0), function (err) {
    t.error(err, 'no append error')
    feed.get(0, function (err, value) {
      t.error(err, 'no get error')
      t.same(value, Buffer(0), 'empty buffer')
      t.end()
    })
  })
})

// tests below was generated by a randomizer triggering different replication edge cases

tape('chaos monkey generated #1', function (t) {
  var ops = []
  ops.push({type: 'append', value: '998'})
  ops.push({type: 'copy', block: 0, from: 'feed', to: 'clone1'})
  runOps(t, ops)
})

tape('chaos monkey generated #2', function (t) {
  var ops = []
  ops.push({type: 'append', value: '993'})
  ops.push({type: 'append', value: '992'})
  ops.push({type: 'append', value: '991'})
  ops.push({type: 'copy', block: 0, from: 'feed', to: 'clone1'})
  ops.push({type: 'append', value: '984'})
  ops.push({type: 'copy', block: 1, from: 'feed', to: 'clone1'})
  ops.push({type: 'append', value: '982'})
  ops.push({type: 'copy', block: 0, from: 'clone1', to: 'clone2'})
  ops.push({type: 'copy', block: 3, from: 'feed', to: 'clone1'})
  runOps(t, ops)
})

tape('chaos monkey generated #3', function (t) {
  var ops = []
  ops.push({type: 'append', value: '996'})
  ops.push({type: 'append', value: '994'})
  ops.push({type: 'copy', block: 1, from: 'feed', to: 'clone1'})
  ops.push({type: 'copy', block: 1, from: 'clone1', to: 'clone2'})
  ops.push({type: 'append', value: '991'})
  ops.push({type: 'append', value: '990'})
  ops.push({type: 'append', value: '988'})
  ops.push({type: 'append', value: '985'})
  ops.push({type: 'copy', block: 5, from: 'feed', to: 'clone1'})
  ops.push({type: 'copy', block: 5, from: 'clone1', to: 'clone2'})
  ops.push({type: 'append', value: '981'})
  ops.push({type: 'append', value: '980'})
  ops.push({type: 'append', value: '976'})
  ops.push({type: 'append', value: '974'})
  ops.push({type: 'append', value: '972'})
  ops.push({type: 'append', value: '971'})
  ops.push({type: 'append', value: '969'})
  ops.push({type: 'copy', block: 8, from: 'feed', to: 'clone1'})
  ops.push({type: 'copy', block: 8, from: 'clone1', to: 'clone2'})
  ops.push({type: 'append', value: '965'})
  ops.push({type: 'copy', block: 6, from: 'feed', to: 'clone1'})
  ops.push({type: 'copy', block: 3, from: 'feed', to: 'clone1'})
  ops.push({type: 'append', value: '961'})
  ops.push({type: 'copy', block: 6, from: 'clone1', to: 'clone2'})
  ops.push({type: 'append', value: '957'})
  ops.push({type: 'append', value: '956'})
  ops.push({type: 'copy', block: 3, from: 'clone1', to: 'clone2'})
  ops.push({type: 'append', value: '953'})
  ops.push({type: 'append', value: '952'})
  ops.push({type: 'append', value: '951'})
  ops.push({type: 'append', value: '950'})
  ops.push({type: 'copy', block: 17, from: 'feed', to: 'clone1'})
  ops.push({type: 'append', value: '947'})
  ops.push({type: 'append', value: '946'})
  ops.push({type: 'copy', block: 18, from: 'feed', to: 'clone1'})
  ops.push({type: 'append', value: '944'})
  ops.push({type: 'copy', block: 22, from: 'feed', to: 'clone1'})
  runOps(t, ops)
})

tape('chaos monkey randomized', function (t) {
  var feed = hypercore().createFeed()
  var clone1 = hypercore().createFeed(feed.key)
  var clone2 = hypercore().createFeed(feed.key)
  var names = ['feed', 'clone1', 'clone2']
  var runs = 500

  loop()

  function loop () {
    if (--runs === 0) return t.end()
    if (Math.random() < 0.3) {
      return feed.append('' + runs, loop)
    }
    if (Math.random() < 0.5) return process.nextTick(loop)

    var from = [feed, clone1, clone2][(Math.random() * 3) | 0]
    var to = null
    if (from === clone1) to = clone2
    else if (from === clone2) to = clone1
    else to = [clone1, clone1][(Math.random() * 2) | 0]

    var blk = -1
    var seen = 0

    for (var i = 0; i < from.bitfield.length; i++) {
      if (!from.has(i) || to.has(i)) continue
      if (Math.random() < 1 / ++seen) blk = i
    }

    if (blk === -1) return process.nextTick(loop)

    copy(blk, from, to, function (err) {
      if (err) {
        t.fail('failed to copy ' + blk + ' from ' + name(from) + ' to ' + name(to))
        t.end()
        return
      }

      t.pass('copied ' + blk + ' from ' + name(from) + ' to ' + name(to))
      loop()
    })
  }

  function name (f) {
    return names[[feed, clone1, clone2].indexOf(f)]
  }
})

function runOps (t, ops) {
  var feed = hypercore().createFeed()
  var clone1 = hypercore().createFeed(feed.key)
  var clone2 = hypercore().createFeed(feed.key)

  loop()

  function get (name) {
    if (name === 'feed') return feed
    if (name === 'clone1') return clone1
    return clone2
  }

  function loop () {
    var next = ops.shift()
    if (!next) {
      t.end()
      return
    }
    if (next.type === 'append') {
      feed.append(next.value, loop)
      return
    }
    if (next.type === 'copy') {
      copy(next.block, get(next.from), get(next.to), function (err) {
        if (err) {
          t.fail('failed to copy ' + next.block + ' from ' + next.from + ' to ' + next.to)
          t.end()
          return
        }
        t.pass('copied ' + next.block + ' from ' + next.from + ' to ' + next.to)
        loop()
      })
      return
    }
  }
}
<|endoftext|>


<commit_before>(function (window, $, undefined) {

    function DeferredLocalFileSystem() {
        this.TEMPORARY = window.TEMPORARY;
        this.PERSISTENT = window.PERSISTENT;
    };

    var requestFileSystemDeferred = function requestFileSystemDeferred(type, size) {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (fileSystem) {
                d.resolve(new DeferredFileSystem(fileSystem));
            };

        window.requestFileSystem(type, size, successCallback, errorCallback);

        return d.promise();
    };

    var resolveLocalFileSystemURLDeferred = function resolveLocalFileSystemURLDeferred(url) {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entry) {
                d.resolve(new DeferredEntry(entry));
            };

        window.resolveLocalFileSystemURL(url, successCallback, errorCallback);

        return d.promise();
    };

    function DeferredFileSystem(fileSystem) {
        var self = this;

        //
        self.fileSystem = fileSystem;

        //
        self.name = fileSystem.name;
        self.root = new DeferredEntry(fileSystem.root);
    };

    function DeferredEntry(entry) {
        var self = this;

        //
        self.entry = entry;

        //
        self.isFile = entry.isFile;
        self.isDirectory = entry.isDirectory;
        self.name = entry.name;
        self.fullPath = entry.fullPath;
        self.filesystem = entry.filesystem;
    };

    DeferredEntry.prototype.getMetadata = function getMetadata() {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (metadata) {
                d.resolve(metadata);
            };

        self.entry.getMetadata(successCallback, errorCallback);

        return d.promise();
    };

    DeferredEntry.prototype.copyTo = function copyTo(parent, newName) {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entry) {
                d.resolve(new DeferredEntry(entry));
            };

        self.entry.copyTo(parent, newName, successCallback, errorCallback);

        return d.promise();
    };

    DeferredEntry.prototype.moveTo = function moveTo(parent, newName) {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entry) {
                d.resolve(new DeferredEntry(entry));
            };

        self.entry.moveTo(parent, newName, successCallback, errorCallback);

        return d.promise();
    };

    DeferredEntry.prototype.remove = function remove() {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function () {
                d.resolve();
            };

        self.entry.remove(successCallback, errorCallback);

        return d.promise();
    };

    DeferredEntry.prototype.toURL = function toURL() {
        var self = this;

        return self.entry.toURL();
    };

    DeferredEntry.prototype.getParent = function getParent() {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entry) {
                d.resolve(new DeferredEntry(entry));
            };

        self.entry.remove(successCallback, errorCallback);

        return d.promise();
    };

    function DeferredFileEntry(fileEntry) {
        this.entry = fileEntry;
    };

    DeferredFileEntry.prototype.createWriter = function createWriter() {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (fileWriter) {
                d.resolve(fileWriter);
            };

        self.entry.createWriter(successCallback, errorCallback);

        return d.promise();
    };

    DeferredFileEntry.prototype.file = function file() {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (file) {
                d.resolve(file);
            };

        self.entry.file(successCallback, errorCallback);

        return d.promise();
    };

    function DeferredDirectoryEntry(directoryEntry) {
        this.entry = directoryEntry;
    };

    DeferredDirectoryEntry.prototype.createReader = function createReader() {
        return new DeferredDirectoryReader(self.directoryEntry.createReader());
    };

    DeferredDirectoryEntry.prototype.getFile = function getFile(path, options) {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entry) {
                d.resolve(new DeferredEntry(entry));
            };

        self.entry.getFile(path, options, successCallback, errorCallback);

        return d.promise();
    };

    DeferredDirectoryEntry.prototype.getDirectory = function getDirectory(path, options) {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entry) {
                d.resolve(new DeferredEntry(entry));
            };

        self.entry.getDirectory(path, options, successCallback, errorCallback);

        return d.promise();
    };

    DeferredDirectoryEntry.prototype.removeRecursively = function removeRecursively() {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function () {
                d.resolve();
            };

        self.entry.remove(successCallback, errorCallback);

        return d.promise();
    };

    function DeferredDirectoryReader(directoryReader) {
        this.directoryReader = directoryReader;
    };

    DeferredDirectoryReader.prototype.readEntries = function readEntries() {
        var self = this,
            d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entries) {
                //wrap entries in 'Deferred' object.

                d.resolve(entries);
            };

        self.directoryReader.readEntries(successCallback, errorCallback);

        return d.promise();
    };

    window.requestFileSystemDeferred = requestFileSystemDeferred;
    window.resolveLocalFileSystemURLDeferred = resolveLocalFileSystemURLDeferred;

})(window, jQuery);
<commit_msg>Wrap FileEntry objects properly as Files or Directories<commit_after>(function (window, $, undefined) {

    function DeferredLocalFileSystem() {
        this.TEMPORARY = window.TEMPORARY;
        this.PERSISTENT = window.PERSISTENT;
    };

    var requestFileSystemDeferred = function requestFileSystemDeferred(type, size) {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (fileSystem) {
                d.resolve(new DeferredFileSystem(fileSystem));
            },
            requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;

        requestFileSystem(type, size, successCallback, errorCallback);

        return d.promise();
    };

    var resolveLocalFileSystemURLDeferred = function resolveLocalFileSystemURLDeferred(url) {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entry) {
                d.resolve(wrapEntry(entry, new DeferredFileSystem(entry.fileSystem)));
            },
            resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;

        resolveLocalFileSystemURL(url, successCallback, errorCallback);

        return d.promise();
    };

    function DeferredFileSystem(fileSystem) {
        this._fileSystem = fileSystem;

        this.name = fileSystem.name;
        this.root = wrapEntry(fileSystem.root, this);
    };

    function DeferredEntry(entry) {
        this._entry = entry;
    };

    DeferredEntry.prototype.getMetadata = function getMetadata() {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (metadata) {
                d.resolve(metadata);
            };

        this._entry.getMetadata(successCallback, errorCallback);

        return d.promise();
    };

    DeferredEntry.prototype.copyTo = function copyTo(parent, newName) {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entry) {
                d.resolve(wrapEntry(entry, this._entry.fileSystem));
            };

        this._entry.copyTo(parent, newName, successCallback, errorCallback);

        return d.promise();
    };

    DeferredEntry.prototype.moveTo = function moveTo(parent, newName) {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entry) {
                d.resolve(wrapEntry(entry, this._entry.fileSystem));
            };

        this._entry.moveTo(parent, newName, successCallback, errorCallback);

        return d.promise();
    };

    DeferredEntry.prototype.remove = function remove() {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function () {
                d.resolve();
            };

        this._entry.remove(successCallback, errorCallback);

        return d.promise();
    };

    DeferredEntry.prototype.toURL = function toURL() {
        return this.entry.toURL();
    };

    DeferredEntry.prototype.getParent = function getParent() {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entry) {
                d.resolve(wrapEntry(entry, this._entry.fileSystem));
            };

        this._entry.remove(successCallback, errorCallback);

        return d.promise();
    };

    window.DeferredFileEntry = function DeferredFileEntry(fileEntry, fileSystem) {
        DeferredEntry.call(this, fileEntry);

        this.isFile = fileEntry.isFile;
        this.isDirectory = fileEntry.isDirectory;
        this.name = fileEntry.name;
        this.fullPath = fileEntry.fullPath;
        this.filesystem = filesystem;
    };

    DeferredFileEntry.prototype = new DeferredEntry();

    DeferredFileEntry.prototype.createWriter = function createWriter() {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (fileWriter) {
                d.resolve(fileWriter);
            };

        this._entry.createWriter(successCallback, errorCallback);

        return d.promise();
    };

    DeferredFileEntry.prototype.file = function file() {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (file) {
                d.resolve(file);
            };

        this._entry.file(successCallback, errorCallback);

        return d.promise();
    };

    window.DeferredDirectoryEntry = function DeferredDirectoryEntry(directoryEntry, fileSystem) {
        DeferredEntry.call(this, directoryEntry);

        this.isFile = directoryEntry.isFile;
        this.isDirectory = directoryEntry.isDirectory;
        this.name = directoryEntry.name;
        this.fullPath = directoryEntry.fullPath;
        this.filesystem = fileSystem;
    };

    DeferredDirectoryEntry.prototype = new DeferredEntry();

    DeferredDirectoryEntry.prototype.createReader = function createReader() {
        return new DeferredDirectoryReader(this._entry.createReader());
    };

    DeferredDirectoryEntry.prototype = new DeferredEntry();

    DeferredDirectoryEntry.prototype.getFile = function getFile(path, options) {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entry) {
                d.resolve(wrapEntry(entry, this._entry.fileSystem));
            };

        this._entry.getFile(path, options, successCallback, errorCallback);

        return d.promise();
    };

    DeferredDirectoryEntry.prototype.getDirectory = function getDirectory(path, options) {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entry) {
                d.resolve(wrapEntry(entry, this._entry.fileSystem));
            };

        this._entry.getDirectory(path, options, successCallback, errorCallback);

        return d.promise();
    };

    DeferredDirectoryEntry.prototype.removeRecursively = function removeRecursively() {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function () {
                d.resolve();
            };

        this._entry.remove(successCallback, errorCallback);

        return d.promise();
    };

    function DeferredDirectoryReader(directoryReader) {
        this._directoryReader = directoryReader;
    };

    DeferredDirectoryReader.prototype.readEntries = function readEntries() {
        var d = $.Deferred(),
            errorCallback = function (error) {
                d.reject(error);
            },
            successCallback = function (entries) {
                //wrap entries in 'Deferred' object.

                d.resolve(entries);
            };

        this._directoryReader.readEntries(successCallback, errorCallback);

        return d.promise();
    };

    function wrapEntry(entry, fileSystem) {
        if (entry.isFile) {
            return new DeferredFileEntry(entry, fileSystem);
        } else if (entry.isDirectory) {
            return new DeferredDirectoryEntry(entry, fileSystem);
        }
    }

    window.requestFileSystemDeferred = requestFileSystemDeferred;
    window.resolveLocalFileSystemURLDeferred = resolveLocalFileSystemURLDeferred;

})(window, jQuery);
<|endoftext|>


<commit_before>import '../src'
import bufferEqual from 'buffer-equal'
import gulp from 'gulp'
import timeout from 'timeout-then'
import rump from 'rump'
import {colors} from 'gulp-util'
import {readFile, writeFile} from 'mz/fs'
import {sep} from 'path'
import {spy} from 'sinon'

const {stripColor} = colors

describe('tasks', () => {
  beforeEach(() => {
    rump.configure({paths: {
      source: {root: 'test/src', static: ''},
      destination: {root: 'tmp'},
    }})
  })

  it('are added and defined', () => {
    const callback = spy()
    rump.on('gulp:main', callback)
    rump.on('gulp:static', callback)
    rump.addGulpTasks({prefix: 'spec'})
    callback.should.be.calledTwice()
    gulp.tasks['spec:info:static'].should.be.ok()
    gulp.tasks['spec:build:static'].should.be.ok()
    gulp.tasks['spec:watch:static'].should.be.ok()
  })

  it('display correct information in info task', () => {
    const logs = [],
          {log} = console
    console.log = (...args) => logs.push(stripColor(args.join(' ')))
    gulp.start('spec:info')
    console.log = log
    logs.slice(-6).should.eql([
      '',
      '--- Static v0.7.0',
      `Static files from test${sep}src are copied to tmp`,
      'Affected files:',
      'index.html',
      '',
    ])
  })

  describe('for building', () => {
    let original

    before(async() => {
      await writeFile('test/src/index.html', original)
    })

    before(done => {
      gulp.task('postbuild', ['spec:watch'], () => done())
      gulp.start('postbuild')
    })

    it('handles updates', async() => {
      let content = await readFile('tmp/index.html')
      bufferEqual(content, original).should.be.true()
      await timeout(800)
      await writeFile('test/src/index.html', '
New
')
      await timeout(800)
      content = await readFile('tmp/index.html')
      bufferEqual(content, original).should.be.false()
    })
  })
})
<commit_msg>Add back after action<commit_after>import '../src'
import bufferEqual from 'buffer-equal'
import gulp from 'gulp'
import timeout from 'timeout-then'
import rump from 'rump'
import {colors} from 'gulp-util'
import {readFile, writeFile} from 'mz/fs'
import {sep} from 'path'
import {spy} from 'sinon'

const {stripColor} = colors

describe('tasks', () => {
  beforeEach(() => {
    rump.configure({paths: {
      source: {root: 'test/src', static: ''},
      destination: {root: 'tmp'},
    }})
  })

  it('are added and defined', () => {
    const callback = spy()
    rump.on('gulp:main', callback)
    rump.on('gulp:static', callback)
    rump.addGulpTasks({prefix: 'spec'})
    callback.should.be.calledTwice()
    gulp.tasks['spec:info:static'].should.be.ok()
    gulp.tasks['spec:build:static'].should.be.ok()
    gulp.tasks['spec:watch:static'].should.be.ok()
  })

  it('display correct information in info task', () => {
    const logs = [],
          {log} = console
    console.log = (...args) => logs.push(stripColor(args.join(' ')))
    gulp.start('spec:info')
    console.log = log
    logs.slice(-6).should.eql([
      '',
      '--- Static v0.7.0',
      `Static files from test${sep}src are copied to tmp`,
      'Affected files:',
      'index.html',
      '',
    ])
  })

  describe('for building', () => {
    let original

    before(async(done) => {
      original = await readFile('test/src/index.html')
      gulp.task('postbuild', ['spec:watch'], () => done())
      gulp.start('postbuild')
    })

    after(async() => await writeFile('test/src/index.html', original))

    it('handles updates', async() => {
      let content = await readFile('tmp/index.html')
      bufferEqual(content, original).should.be.true()
      await timeout(800)
      await writeFile('test/src/index.html', '
New
')
      await timeout(800)
      content = await readFile('tmp/index.html')
      bufferEqual(content, original).should.be.false()
    })
  })
})
<|endoftext|>