<commit_before>var connect = require('connect')
  , assert = require('assert')
  , proxy = require('../')
  , fs = require('fs')
  , url = require('url')
  , path = require('path')
  , http = require('http')
  , exec = require('child_process').exec
  , key = fs.readFileSync(path.join(__dirname, "server.key"))
  , cert = fs.readFileSync(path.join(__dirname, "server.crt"))

describe("proxy", function() {
  it("http -> https", function(done) {
    testWith('http', 'https', done);
  });

  it("https -> http", function(done) {
    testWith('https', 'http', done);
  });

  it("http -> http", function(done) {
    testWith('http', 'http', done);
  });

  it("https -> https", function(done) {
    testWith('https', 'https', done);
  });

  it("Can still proxy empty requests if the request stream has ended.", function(done) {
    var destServer = createServerWithLibName('http', function(req, resp) {
      resp.statusCode = 200;
      resp.write(req.url);
      resp.end();
    });

    var app = connect();
    //connect.directory causes the incoming request stream to be ended for GETs.
    app.use(connect.directory(path.resolve('.')));
    app.use('/foo', proxy(url.parse('http://localhost:8001/')));

    destServer.listen(8001, 'localhost', function() {
      app.listen(8000);
      http.get('http://localhost:8000/foo/test/', function(res) {
        var data = '';
        res.on('data', function (chunk) {
          data += chunk;
        });
        res.on('end', function () {
          assert.strictEqual(data, '/test/');
          destServer.close();
          done();
        });
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("can proxy just the given route.", function(done) {
    var destServer = createServerWithLibName('http', function(req, resp) {
      resp.statusCode = 200;
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8003/');
    proxyOptions.route = '/foo';

    var app = connect(
      connect.directory(path.resolve('.')),
      // we must pass the route within the options here
      proxy(proxyOptions)
    );

    destServer.listen(8003, 'localhost', function() {
      app.listen(8002);
      http.get('http://localhost:8002/foo/test/', function(res) {
        var data = '';
        res.on('data', function (chunk) {
          data += chunk;
        });
        res.on('end', function () {
          assert.strictEqual(data, '/test/');
          destServer.close();
          done();
        });
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("Does not keep header data across requests", function(done) {
    var headerValues = ['foo', 'bar'];
    var reqIdx = 0;

    var destServer = createServerWithLibName('http', function(req, resp) {
      assert.strictEqual(req.headers['some-header'], headerValues[reqIdx]);
      reqIdx++;
      resp.statusCode = 200;
      resp.write(req.url);
      resp.end();
    });

    var app = connect(proxy(url.parse('http://localhost:8005/')));

    destServer.listen(8005, 'localhost', function() {
      app.listen(8004);

      var options = url.parse('http://localhost:8004/foo/test/');

      //Get with 0 content length, then 56;
      options.headers = {'some-header': headerValues[0]};
      http.get(options, function () {

        options.headers['some-header'] = headerValues[1];
        http.get(options, function () {
          destServer.close();
          done();
        }).on('error', function () {
          assert.fail('Request proxy failed');
        });

      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("correctly applies the via header to the request", function(done) {

    var destServer = createServerWithLibName('http', function(req, resp) {
      assert.strictEqual(req.headers.via, '1.1 my-proxy-name');
      resp.statusCode = 200;
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8015/');
    proxyOptions.via = 'my-proxy-name';
    var app = connect(proxy(proxyOptions));

    destServer.listen(8015, 'localhost', function() {
      app.listen(8014);

      var options = url.parse('http://localhost:8014/foo/test/');

      http.get(options, function () {
        // ok...
        done();
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("correctly applies the via header to the request where the request has an existing via header", function(done) {

    var destServer = createServerWithLibName('http', function(req, resp) {
      assert.strictEqual(req.headers.via, '1.0 other-proxy-name, 1.1 my-proxy-name');
      resp.statusCode = 200;
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8025/');
    proxyOptions.via = 'my-proxy-name';
    var app = connect(proxy(proxyOptions));

    destServer.listen(8025, 'localhost', function() {
      app.listen(8024);

      var options = url.parse('http://localhost:8024/foo/test/');
      options.headers = {via: '1.0 other-proxy-name'};

      http.get(options, function () {
        // ok...
        done();
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("correctly applies the via header to the response", function(done) {

    var destServer = createServerWithLibName('http', function(req, resp) {
      resp.statusCode = 200;
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8035/');
    proxyOptions.via = 'my-proxy-name';
    var app = connect(proxy(proxyOptions));

    destServer.listen(8035, 'localhost', function() {
      app.listen(8034);

      var options = url.parse('http://localhost:8034/foo/test/');

      http.get(options, function (res) {
        assert.strictEqual('1.1 my-proxy-name', res.headers.via);
        done();
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("correctly applies the via header to the response where the response has an existing via header", function(done) {

    var destServer = createServerWithLibName('http', function(req, resp) {
      resp.statusCode = 200;
      resp.setHeader('via', '1.0 other-proxy-name');
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8045/');
    proxyOptions.via = 'my-proxy-name';
    var app = connect(proxy(proxyOptions));

    destServer.listen(8045, 'localhost', function() {
      app.listen(8044);

      var options = url.parse('http://localhost:8044/foo/test/');

      http.get(options, function (res) {
        assert.strictEqual('1.0 other-proxy-name, 1.1 my-proxy-name', res.headers.via);
        done();
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("correctly apllies the location header to the response when the response status code is 3xx", function(done) {
    var destServer = createServerWithLibName('http', function(req, resp) {
      resp.statusCode = 302;
      resp.setHeader('location', 'http://localhost:8055/foo/redirect/');
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8055/');
    var app = connect(proxy(proxyOptions));

    destServer.listen(8055, 'localhost', function() {
      app.listen(8054);

      var options = url.parse('http://localhost:8054/foo/test/');

      http.get(options, function (res) {
        assert.strictEqual('/foo/redirect/', res.headers.location);
        done();
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    })
  });

});

function createServerWithLibName(libName, requestListener) {
  var httpLib = require(libName);
  if (libName === "http") {
    return httpLib.createServer(requestListener);
  } else {
    return httpLib.createServer({key: key, cert: cert}, requestListener);
  }
}

function testWith (srcLibName, destLibName, cb) {
  var srcHttp = require(srcLibName);
  var destHttp = require(destLibName);

  var destServer = createServerWithLibName(destLibName, function(req, resp) {
    assert.strictEqual(req.method, 'GET');
    assert.strictEqual(req.headers['x-custom-header'], 'hello');
    assert.strictEqual(req.url, '/api/a/b/c/d');
    resp.statusCode = 200;
    resp.setHeader('x-custom-reply', "la la la");
    resp.write('this is your body.');
    resp.end();
  });
  destServer.listen(0, 'localhost', function() {
    var app = connect();
    var destEndpoint = destLibName + "://localhost:" + destServer.address().port + "/api";
    var reqOpts = url.parse(destEndpoint);
    reqOpts.rejectUnauthorized = false; // because we're self-signing for tests
    app.use(proxy(reqOpts));
    var srcServer = createServerWithLibName(srcLibName, app);
    srcServer.listen(0, 'localhost', function() {
      // make client request to proxy server
      var srcRequest = srcHttp.request({
        port: srcServer.address().port,
        method: "GET",
        path: "/a/b/c/d",
        headers: {
          "x-custom-header": "hello"
        },
        rejectUnauthorized: false
      }, function (resp) {
        var buffer = "";
        assert.strictEqual(resp.statusCode, 200);
        assert.strictEqual(resp.headers['x-custom-reply'], 'la la la');
        resp.setEncoding('utf8');
        resp.on('data', function(data) {
          buffer += data;
        });
        resp.on('end', function() {
          assert.strictEqual(buffer, 'this is your body.');
          srcServer.close();
          destServer.close();
          cb();
        });
      });
      srcRequest.end();
    });
  });
}
<commit_msg>Added tests for cookie rewriting.<commit_after>var connect = require('connect')
  , assert = require('assert')
  , proxy = require('../')
  , fs = require('fs')
  , url = require('url')
  , path = require('path')
  , http = require('http')
  , exec = require('child_process').exec
  , key = fs.readFileSync(path.join(__dirname, "server.key"))
  , cert = fs.readFileSync(path.join(__dirname, "server.crt"))

describe("proxy", function() {
  it("http -> https", function(done) {
    testWith('http', 'https', done);
  });

  it("https -> http", function(done) {
    testWith('https', 'http', done);
  });

  it("http -> http", function(done) {
    testWith('http', 'http', done);
  });

  it("https -> https", function(done) {
    testWith('https', 'https', done);
  });

  it("Can still proxy empty requests if the request stream has ended.", function(done) {
    var destServer = createServerWithLibName('http', function(req, resp) {
      resp.statusCode = 200;
      resp.write(req.url);
      resp.end();
    });

    var app = connect();
    //connect.directory causes the incoming request stream to be ended for GETs.
    app.use(connect.directory(path.resolve('.')));
    app.use('/foo', proxy(url.parse('http://localhost:8001/')));

    destServer.listen(8001, 'localhost', function() {
      app.listen(8000);
      http.get('http://localhost:8000/foo/test/', function(res) {
        var data = '';
        res.on('data', function (chunk) {
          data += chunk;
        });
        res.on('end', function () {
          assert.strictEqual(data, '/test/');
          destServer.close();
          done();
        });
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("can proxy just the given route.", function(done) {
    var destServer = createServerWithLibName('http', function(req, resp) {
      resp.statusCode = 200;
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8003/');
    proxyOptions.route = '/foo';

    var app = connect(
      connect.directory(path.resolve('.')),
      // we must pass the route within the options here
      proxy(proxyOptions)
    );

    destServer.listen(8003, 'localhost', function() {
      app.listen(8002);
      http.get('http://localhost:8002/foo/test/', function(res) {
        var data = '';
        res.on('data', function (chunk) {
          data += chunk;
        });
        res.on('end', function () {
          assert.strictEqual(data, '/test/');
          destServer.close();
          done();
        });
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("Does not keep header data across requests", function(done) {
    var headerValues = ['foo', 'bar'];
    var reqIdx = 0;

    var destServer = createServerWithLibName('http', function(req, resp) {
      assert.strictEqual(req.headers['some-header'], headerValues[reqIdx]);
      reqIdx++;
      resp.statusCode = 200;
      resp.write(req.url);
      resp.end();
    });

    var app = connect(proxy(url.parse('http://localhost:8005/')));

    destServer.listen(8005, 'localhost', function() {
      app.listen(8004);

      var options = url.parse('http://localhost:8004/foo/test/');

      //Get with 0 content length, then 56;
      options.headers = {'some-header': headerValues[0]};
      http.get(options, function () {

        options.headers['some-header'] = headerValues[1];
        http.get(options, function () {
          destServer.close();
          done();
        }).on('error', function () {
          assert.fail('Request proxy failed');
        });

      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("correctly applies the via header to the request", function(done) {

    var destServer = createServerWithLibName('http', function(req, resp) {
      assert.strictEqual(req.headers.via, '1.1 my-proxy-name');
      resp.statusCode = 200;
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8015/');
    proxyOptions.via = 'my-proxy-name';
    var app = connect(proxy(proxyOptions));

    destServer.listen(8015, 'localhost', function() {
      app.listen(8014);

      var options = url.parse('http://localhost:8014/foo/test/');

      http.get(options, function () {
        // ok...
        done();
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("correctly applies the via header to the request where the request has an existing via header", function(done) {

    var destServer = createServerWithLibName('http', function(req, resp) {
      assert.strictEqual(req.headers.via, '1.0 other-proxy-name, 1.1 my-proxy-name');
      resp.statusCode = 200;
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8025/');
    proxyOptions.via = 'my-proxy-name';
    var app = connect(proxy(proxyOptions));

    destServer.listen(8025, 'localhost', function() {
      app.listen(8024);

      var options = url.parse('http://localhost:8024/foo/test/');
      options.headers = {via: '1.0 other-proxy-name'};

      http.get(options, function () {
        // ok...
        done();
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("correctly applies the via header to the response", function(done) {

    var destServer = createServerWithLibName('http', function(req, resp) {
      resp.statusCode = 200;
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8035/');
    proxyOptions.via = 'my-proxy-name';
    var app = connect(proxy(proxyOptions));

    destServer.listen(8035, 'localhost', function() {
      app.listen(8034);

      var options = url.parse('http://localhost:8034/foo/test/');

      http.get(options, function (res) {
        assert.strictEqual('1.1 my-proxy-name', res.headers.via);
        done();
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("correctly applies the via header to the response where the response has an existing via header", function(done) {

    var destServer = createServerWithLibName('http', function(req, resp) {
      resp.statusCode = 200;
      resp.setHeader('via', '1.0 other-proxy-name');
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8045/');
    proxyOptions.via = 'my-proxy-name';
    var app = connect(proxy(proxyOptions));

    destServer.listen(8045, 'localhost', function() {
      app.listen(8044);

      var options = url.parse('http://localhost:8044/foo/test/');

      http.get(options, function (res) {
        assert.strictEqual('1.0 other-proxy-name, 1.1 my-proxy-name', res.headers.via);
        done();
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    });
  });

  it("correctly apllies the location header to the response when the response status code is 3xx", function(done) {
    var destServer = createServerWithLibName('http', function(req, resp) {
      resp.statusCode = 302;
      resp.setHeader('location', 'http://localhost:8055/foo/redirect/');
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8055/');
    var app = connect(proxy(proxyOptions));

    destServer.listen(8055, 'localhost', function() {
      app.listen(8054);

      var options = url.parse('http://localhost:8054/foo/test/');

      http.get(options, function (res) {
        assert.strictEqual('/foo/redirect/', res.headers.location);
        done();
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    })
  });

  it("correctly rewrites the cookie domain for set-cookie headers", function(done) {
    var cookie1 = function(host) { return 'cookie1=value1; Expires=Fri, 01-Mar-2019 00:00:01 GMT; Path=/; Domain=' + host + '; HttpOnly'; };
    var cookie2 = function(host) { return 'cookie2=value2; Expires=Fri, 01-Mar-2019 00:00:01 GMT; Domain=' + host + '; Path=/test/'; };
    var cookie3 = function(host) { return 'cookie3=value3'; };
    var cookie4 = function(host) { return 'cookie4=value4; Expires=Fri, 01-Mar-2019 00:00:01 GMT; Domain=' + host; };
    var destServer = createServerWithLibName('http', function(req, resp) {
      resp.statusCode = 200;
      resp.setHeader('set-cookie', [
        cookie1('.server.com'),
        cookie2('.server.com'),
        cookie3('.server.com'),
        cookie4('.server.com'),
      ]);
      resp.write(req.url);
      resp.end();
    });

    var proxyOptions = url.parse('http://localhost:8065/');
    proxyOptions.cookieRewrite = ".proxy.com";
    var app = connect(proxy(proxyOptions));

    destServer.listen(8065, 'localhost', function() {
      app.listen(8064);

      var options = url.parse('http://localhost:8064/foo/test/');

      http.get(options, function (res) {
        var cookies = res.headers['set-cookie'];
        assert.strictEqual(cookies[0], cookie1(proxyOptions.cookieRewrite));
        assert.strictEqual(cookies[1], cookie2(proxyOptions.cookieRewrite));
        assert.strictEqual(cookies[2], cookie3(proxyOptions.cookieRewrite));
        assert.strictEqual(cookies[3], cookie4(proxyOptions.cookieRewrite));
        done();
      }).on('error', function () {
        assert.fail('Request proxy failed');
      });
    })
  });

});

function createServerWithLibName(libName, requestListener) {
  var httpLib = require(libName);
  if (libName === "http") {
    return httpLib.createServer(requestListener);
  } else {
    return httpLib.createServer({key: key, cert: cert}, requestListener);
  }
}

function testWith (srcLibName, destLibName, cb) {
  var srcHttp = require(srcLibName);
  var destHttp = require(destLibName);

  var destServer = createServerWithLibName(destLibName, function(req, resp) {
    assert.strictEqual(req.method, 'GET');
    assert.strictEqual(req.headers['x-custom-header'], 'hello');
    assert.strictEqual(req.url, '/api/a/b/c/d');
    resp.statusCode = 200;
    resp.setHeader('x-custom-reply', "la la la");
    resp.write('this is your body.');
    resp.end();
  });
  destServer.listen(0, 'localhost', function() {
    var app = connect();
    var destEndpoint = destLibName + "://localhost:" + destServer.address().port + "/api";
    var reqOpts = url.parse(destEndpoint);
    reqOpts.rejectUnauthorized = false; // because we're self-signing for tests
    app.use(proxy(reqOpts));
    var srcServer = createServerWithLibName(srcLibName, app);
    srcServer.listen(0, 'localhost', function() {
      // make client request to proxy server
      var srcRequest = srcHttp.request({
        port: srcServer.address().port,
        method: "GET",
        path: "/a/b/c/d",
        headers: {
          "x-custom-header": "hello"
        },
        rejectUnauthorized: false
      }, function (resp) {
        var buffer = "";
        assert.strictEqual(resp.statusCode, 200);
        assert.strictEqual(resp.headers['x-custom-reply'], 'la la la');
        resp.setEncoding('utf8');
        resp.on('data', function(data) {
          buffer += data;
        });
        resp.on('end', function() {
          assert.strictEqual(buffer, 'this is your body.');
          srcServer.close();
          destServer.close();
          cb();
        });
      });
      srcRequest.end();
    });
  });
}
<|endoftext|>


<commit_before>//Import dependencies
var assert = require('assert');
var fs = require('fs');
var path = require('path');
var utily = require('../index.js');

//Test the fs methods
describe('utily -> fs', function()
{
  //Test checksum method
  describe('-> checksum method', function()
  {
    var file = path.join(__dirname, './fs-checksum-test.txt');
    fs.writeFileSync(file, 'Hello\nThis is the content\n', 'utf8');
    it('should generate the correct checksum of the file', function(done)
    {
      return utily.fs.checksum(file, 'md5', function(error, sum)
      {
        assert.equal(null, error);
        assert.equal('2c1b03ff58b808e5bd56196131cc8505', sum);
        done();
      });
    });
  });

  //Test copy method
  describe('-> copy method', function()
  {
    //Copy files
    it('shgould copy a file that exists', function(done)
    {
      var file_source = path.join(__dirname, 'fs-copy-source.txt');
      var file_destination = path.join(__dirname, 'fs-copy-destination.txt');
      fs.writeFileSync(file_source, 'This is the content of the file 1', 'utf8');
      return utily.fs.copy(file_source, file_destination, function(error)
      {
        assert.equal(null, error);
        var content1 = fs.readFileSync(file_source, 'utf8');
        var content2 = fs.readFileSync(file_destination, 'utf8');
        assert.equal(content1, content2);
        done();
      });
    });

    //Display an error
    it('should return an error if source file does not exists', function(done)
    {
      var file_source = path.join(__dirname, 'fs-copy-source-unexistent.txt');
      var file_destination = path.join(__dirname, 'fs-copy-destination.txt');
      return utily.fs.copy(file_source, file_destination, function(error)
      {
        assert.notEqual(null, error);
        done();
      });
    });
  });

  //Test exists method
  describe('-> exists method', function()
  {
    //Folder that does not exists
    it('should return false if path does not exists', function(done)
    {
      return utily.fs.exists(path.join(__dirname, './inexistent'), function(error, exists)
      {
        assert.equal(null, error);
        assert.equal(false, exists);
        done();
      });
    });
    //Folder that exists
    it('should return true if path exists', function(done)
    {
      return utily.fs.exists(__dirname, function(error, exists)
      {
        assert.equal(null, error);
        assert.equal(true, exists);
        done();
      });
    });
  });

  //Test mkdir method
  describe('-> mkdir method', function()
  {
    //Create a folder
    it('should create the folders', function(done)
    {
      var folders = path.join(__dirname, './new/folders/yeah');
      return utily.fs.mkdir(folders, function(error)
      {
        assert.equal(null, error);
        assert.equal(true, fs.existsSync(folders));
        done();
      });
    });
  });

  //Test size method
  describe('-> size method', function()
  {
    //Check the file size
    it('should get the real file size', function(done)
    {
      var file = path.join(__dirname, './fs-size-test.txt');
      fs.writeFileSync(file, 'This is the content of the \nfile\n', 'utf8');
      return utily.fs.size(file, function(error, size)
      {
        assert.equal(null, error);
        assert.equal(33, size);
        done();
      });
    });
  });

  //Test unlink method
  describe('-> unlink method', function()
  {
    //Delete a list of file
    it('should delete a list of files', function(done)
    {
      var file1 = path.join(__dirname, './fs-unlink-test1.txt');
      var file2 = path.join(__dirname, './fs-unlink-test2.txt');
      fs.writeFileSync(file1, 'Test 1', 'utf8');
      fs.writeFileSync(file2, 'Test 2', 'utf8');
      return utily.fs.unlink([ file1, file2 ], function(error)
      {
        assert.equal(null, error);
        assert.equal(false, fs.existsSync(file1));
        assert.equal(false, fs.existssync(file2));
        done();
      });
    });
  });
});

<commit_msg>test/test.js: fixed bug<commit_after>//Import dependencies
var assert = require('assert');
var fs = require('fs');
var path = require('path');
var utily = require('../index.js');

//Test the fs methods
describe('utily -> fs', function()
{
  //Test checksum method
  describe('-> checksum method', function()
  {
    var file = path.join(__dirname, './fs-checksum-test.txt');
    fs.writeFileSync(file, 'Hello\nThis is the content\n', 'utf8');
    it('should generate the correct checksum of the file', function(done)
    {
      return utily.fs.checksum(file, 'md5', function(error, sum)
      {
        assert.equal(null, error);
        assert.equal('2c1b03ff58b808e5bd56196131cc8505', sum);
        done();
      });
    });
  });

  //Test copy method
  describe('-> copy method', function()
  {
    //Copy files
    it('shgould copy a file that exists', function(done)
    {
      var file_source = path.join(__dirname, 'fs-copy-source.txt');
      var file_destination = path.join(__dirname, 'fs-copy-destination.txt');
      fs.writeFileSync(file_source, 'This is the content of the file 1', 'utf8');
      return utily.fs.copy(file_source, file_destination, function(error)
      {
        assert.equal(null, error);
        var content1 = fs.readFileSync(file_source, 'utf8');
        var content2 = fs.readFileSync(file_destination, 'utf8');
        assert.equal(content1, content2);
        done();
      });
    });

    //Display an error
    it('should return an error if source file does not exists', function(done)
    {
      var file_source = path.join(__dirname, 'fs-copy-source-unexistent.txt');
      var file_destination = path.join(__dirname, 'fs-copy-destination.txt');
      return utily.fs.copy(file_source, file_destination, function(error)
      {
        assert.notEqual(null, error);
        done();
      });
    });
  });

  //Test exists method
  describe('-> exists method', function()
  {
    //Folder that does not exists
    it('should return false if path does not exists', function(done)
    {
      return utily.fs.exists(path.join(__dirname, './inexistent'), function(error, exists)
      {
        assert.equal(null, error);
        assert.equal(false, exists);
        done();
      });
    });
    //Folder that exists
    it('should return true if path exists', function(done)
    {
      return utily.fs.exists(__dirname, function(error, exists)
      {
        assert.equal(null, error);
        assert.equal(true, exists);
        done();
      });
    });
  });

  //Test mkdir method
  describe('-> mkdir method', function()
  {
    //Create a folder
    it('should create the folders', function(done)
    {
      var folders = path.join(__dirname, './new/folders/yeah');
      return utily.fs.mkdir(folders, function(error)
      {
        assert.equal(null, error);
        assert.equal(true, fs.existsSync(folders));
        done();
      });
    });
  });

  //Test size method
  describe('-> size method', function()
  {
    //Check the file size
    it('should get the real file size', function(done)
    {
      var file = path.join(__dirname, './fs-size-test.txt');
      fs.writeFileSync(file, 'This is the content of the \nfile\n', 'utf8');
      return utily.fs.size(file, function(error, size)
      {
        assert.equal(null, error);
        assert.equal(33, size);
        done();
      });
    });
  });

  //Test unlink method
  describe('-> unlink method', function()
  {
    //Delete a list of file
    it('should delete a list of files', function(done)
    {
      var file1 = path.join(__dirname, './fs-unlink-test1.txt');
      var file2 = path.join(__dirname, './fs-unlink-test2.txt');
      fs.writeFileSync(file1, 'Test 1', 'utf8');
      fs.writeFileSync(file2, 'Test 2', 'utf8');
      return utily.fs.unlink([ file1, file2 ], function(error)
      {
        assert.equal(null, error);
        assert.equal(false, fs.existsSync(file1));
        assert.equal(false, fs.existsSync(file2));
        done();
      });
    });
  });
});

<|endoftext|>


<commit_before>var assert = require('chai').assert;
var set = require('../lib/set');

describe('Set game', function() {

  describe('#set()', function () {

    it('should return true when three cards are a set', function () {
      var cards = [
        "oval open green 2",
        "oval open red 2",
        "oval open blue 2"
      ];
      assert.isTrue(set(cards));
    });

  });

});
<commit_msg>Added failing (so commented) test for 3 cards that are not a set<commit_after>var assert = require('chai').assert;
var set = require('../lib/set');

describe('Set game', function() {

  describe('#set()', function () {

    it('should return true when three cards are a set', function () {
      var cards = [
        "oval open green 2",
        "oval open red 2",
        "oval open blue 2"
      ];
      assert.isTrue(set(cards));
    });

    it('should return false when three cards are not a set');/*, function () {
      var cards = [
        "squiggle solid red 1",
        "squiggle striped blue 1",
        "squiggle solid blue 2"
      ];
      assert.isNotTrue(set(cards));
    });*/

  });

});
<|endoftext|>


<commit_before>/* global describe, it, beforeEach */

var chai, assert, sinon, spy, TreeModel;
chai = require('chai');
sinon = require('sinon');
spy = sinon.spy;
TreeModel = require('../src/TreeModel');
assert = chai.assert;
chai.Assertion.includeStack = true;

describe('TreeModel', function () {
  'use strict';

  function idEq(id) {
    return function (node) {
      return node.model.id === id;
    };
  }

  describe('with default configuration', function () {
    var treeModel;

    beforeEach(function () {
      treeModel = new TreeModel();
    });

    describe('parse()', function () {
      it('should throw an error when model is a number (not an object)', function () {
        assert.throws(treeModel.parse.bind(treeModel, 1), TypeError, 'Model must be of type object.');
      });

      it('should throw an error when model is a string (not an object)', function () {
        assert.throws(treeModel.parse.bind(treeModel, 'string'), TypeError, 'Model must be of type object.');
      });

      it('should throw an error when some child in the model is not an object', function () {
        assert.throws(
          treeModel.parse.bind(treeModel, {children: ['string']}),
          TypeError,
          'Model must be of type object.');
      });

      it('should create a root node when given a model without children', function () {
        var root;

        root = treeModel.parse({id: 1});

        assert.isUndefined(root.parent);
        assert.isArray(root.children);
        assert.lengthOf(root.children, 0);
        assert.deepEqual(root.model, {id: 1});
      });

      it('should create a root and the respective children when given a model with children', function () {
        var root, node12;

        root = treeModel.parse({
          id: 1,
          children: [
            {
              id: 11,
              children: [{id: 111}]
            },
            {
              id: 12,
              children: [{id: 121}, {id: 122}]
            }
          ]
        });

        assert.isUndefined(root.parent);
        assert.isArray(root.children);
        assert.lengthOf(root.children, 2);
        assert.deepEqual(root.model, {
          id: 1,
          children: [
            {
              id: 11,
              children: [{id: 111}]
            },
            {
              id: 12,
              children: [{id: 121}, {id: 122}]
            }
          ]
        });

        assert.deepEqual(root, root.children[0].parent);
        assert.deepEqual(root, root.children[1].parent);

        node12 = root.children[1];
        assert.isArray(node12.children);
        assert.lengthOf(node12.children, 2);
        assert.deepEqual(node12.model, {
          id: 12,
          children: [{id: 121}, {id: 122}]
        });

        assert.deepEqual(node12, node12.children[0].parent);
        assert.deepEqual(node12, node12.children[1].parent);
      });
    });

    describe('addChild()', function () {
      var root;

      beforeEach(function () {
        root = treeModel.parse({id: 1, children: [{id: 11}, {id: 12}]});
      });

      it('should add child to the end', function () {
        root.addChild(treeModel.parse({id: 13}));
        root.addChild(treeModel.parse({id: 10}));
        assert.deepEqual(root.model.children, [{id: 11}, {id: 12}, {id: 13}, {id: 10}]);
      });
    });

    describe('getPath()', function () {
      var root;

      beforeEach(function () {
        root = treeModel.parse({
          id: 1,
          children: [
            {
              id: 11,
              children: [{id: 111}]
            },
            {
              id: 12,
              children: [{id: 121}, {id: 122}]
            }
          ]
        });
      });

      it('should get an array with the root node if called on the root node', function () {
        var pathToRoot;
        pathToRoot = root.getPath();
        assert.lengthOf(pathToRoot, 1);
        assert.strictEqual(pathToRoot[0].model.id, 1);
      });

      it('should get an array of nodes from the root to the node (included)', function () {
        var pathToNode121;
        pathToNode121 = root.first(idEq(121)).getPath();
        assert.lengthOf(pathToNode121, 3);
        assert.strictEqual(pathToNode121[0].model.id, 1);
        assert.strictEqual(pathToNode121[1].model.id, 12);
        assert.strictEqual(pathToNode121[2].model.id, 121);
      });
    });

    describe('traversal', function () {
      var root, spy121, spy12;

      function callback121(node) {
        if (node.model.id === 121) {
          return false;
        }
      }

      function callback12(node) {
        if (node.model.id === 12) {
          return false;
        }
      }

      beforeEach(function () {
        root = treeModel.parse({
          id: 1,
          children: [
            {
              id: 11,
              children: [{id: 111}]
            },
            {
              id: 12,
              children: [{id: 121}, {id: 122}]
            }
          ]
        });

        spy121 = sinon.spy(callback121);
        spy12 = sinon.spy(callback12);
      });

      describe('walk depthFirstPreOrder by default', function () {
        it('should traverse the nodes until the callback returns false', function () {
          root.walk(spy121, this);
          assert.strictEqual(spy121.callCount, 5);
          assert(spy121.alwaysCalledOn(this));
          assert(spy121.getCall(0).calledWithExactly(root.first(idEq(1))));
          assert(spy121.getCall(1).calledWithExactly(root.first(idEq(11))));
          assert(spy121.getCall(2).calledWithExactly(root.first(idEq(111))));
          assert(spy121.getCall(3).calledWithExactly(root.first(idEq(12))));
          assert(spy121.getCall(4).calledWithExactly(root.first(idEq(121))));
        });
      });

      describe('walk depthFirstPostOrder', function () {
        it('should traverse the nodes until the callback returns false', function () {
          root.walk({strategy: 'post'}, spy121, this);
          assert.strictEqual(spy121.callCount, 3);
          assert(spy121.alwaysCalledOn(this));
          assert(spy121.getCall(0).calledWithExactly(root.first(idEq(111))));
          assert(spy121.getCall(1).calledWithExactly(root.first(idEq(11))));
          assert(spy121.getCall(2).calledWithExactly(root.first(idEq(121))));
        });
      });

      describe('walk depthFirstPostOrder (2)', function () {
        it('should traverse the nodes until the callback returns false', function () {
          root.walk({strategy: 'post'}, spy12, this);
          assert.strictEqual(spy12.callCount, 5);
          assert(spy12.alwaysCalledOn(this));
          assert(spy12.getCall(0).calledWithExactly(root.first(idEq(111))));
          assert(spy12.getCall(1).calledWithExactly(root.first(idEq(11))));
          assert(spy12.getCall(2).calledWithExactly(root.first(idEq(121))));
          assert(spy12.getCall(3).calledWithExactly(root.first(idEq(122))));
          assert(spy12.getCall(4).calledWithExactly(root.first(idEq(12))));
        });
      });

      describe('walk breadthFirst', function () {
        it('should traverse the nodes until the callback returns false', function () {
          root.walk({strategy: 'breadth'}, spy121, this);
          assert.strictEqual(spy121.callCount, 5);
          assert(spy121.alwaysCalledOn(this));
          assert(spy121.getCall(0).calledWithExactly(root.first(idEq(1))));
          assert(spy121.getCall(1).calledWithExactly(root.first(idEq(11))));
          assert(spy121.getCall(2).calledWithExactly(root.first(idEq(12))));
          assert(spy121.getCall(3).calledWithExactly(root.first(idEq(111))));
          assert(spy121.getCall(4).calledWithExactly(root.first(idEq(121))));
        });
      });

      describe('walk using unknown strategy', function () {
        it('should throw an error warning about the strategy', function () {
          assert.throws(
            root.walk.bind(root, {strategy: 'unknownStrategy'}, callback121, this),
            Error,
            'Unknown tree walk strategy. Valid strategies are \'pre\' [default], \'post\' and \'breadth\'.');
        });
      });
    });

    describe('all()', function () {
      var root;

      beforeEach(function () {
        root = treeModel.parse({
          id: 1,
          children: [
            {
              id: 11,
              children: [{id: 111}]
            },
            {
              id: 12,
              children: [{id: 121}, {id: 122}]
            }
          ]
        });
      });

      it('should get an empty array if no nodes match the predicate', function () {
        var idLt0;
        idLt0 = root.all(function (node) {
          return node.model.id < 0;
        });
        assert.lengthOf(idLt0, 0);
      });

      it('should get an array with the node itself if only the node matches the predicate', function () {
        var idEq1;
        idEq1 = root.all(idEq(1));
        assert.lengthOf(idEq1, 1);
        assert.deepEqual(idEq1[0], root);
      });

      it('should get an array with all nodes that match a given predicate', function () {
        var idGt100;
        idGt100 = root.all(function (node) {
          return node.model.id > 100;
        });
        assert.lengthOf(idGt100, 3);
        assert.strictEqual(idGt100[0].model.id, 111);
        assert.strictEqual(idGt100[1].model.id, 121);
        assert.strictEqual(idGt100[2].model.id, 122);
      });

      it('should get an array with all nodes that match a given predicate (2)', function () {
        var idGt10AndChildOfRoot;
        idGt10AndChildOfRoot = root.all(function (node) {
          return node.model.id > 10 && node.parent === root;
        });
        assert.lengthOf(idGt10AndChildOfRoot, 2);
        assert.strictEqual(idGt10AndChildOfRoot[0].model.id, 11);
        assert.strictEqual(idGt10AndChildOfRoot[1].model.id, 12);
      });
    });

    describe('drop()', function () {
      var root;

      beforeEach(function () {
        root = treeModel.parse({
          id: 1,
          children: [
            {
              id: 11,
              children: [{id: 111}]
            },
            {
              id: 12,
              children: [{id: 121}, {id: 122}]
            }
          ]
        });
      });

      it('should give back the dropped node, even if it is the root', function () {
        assert.deepEqual(root.drop(), root);
      });

      it('should give back the dropped node, which no longer be found in the original root', function () {
        assert.deepEqual(root.first(idEq(11)).drop().model, {id: 11, children: [{id: 111}]});
        assert.isUndefined(root.first(idEq(11)));
      });
    });
  });

  describe('with custom children and comparator', function () {
    var treeModel;

    beforeEach(function () {
      treeModel = new TreeModel({
        childrenPropertyName: 'deps',
        modelComparatorFn: function (a, b) {
          return b.id - a.id;
        }
      });
    });

    describe('parse()', function () {
      it('should create a root and sort the respective children according to the comparator', function () {
        var root, node12;

        root = treeModel.parse({
          id: 1,
          deps: [
            {
              id: 11,
              deps: [{id: 111}]
            },
            {
              id: 12,
              deps: [{id: 121}, {id: 122}]
            }
          ]
        });

        assert.isUndefined(root.parent);
        assert.isArray(root.children);
        assert.lengthOf(root.children, 2);
        assert.deepEqual(root.model, {
          id: 1,
          deps: [
            {
              id: 12,
              deps: [{id: 122}, {id: 121}]
            },
            {
              id: 11,
              deps: [{id: 111}]
            }
          ]
        });

        assert.deepEqual(root, root.children[0].parent);
        assert.deepEqual(root, root.children[1].parent);

        node12 = root.children[0];
        assert.isArray(node12.children);
        assert.lengthOf(node12.children, 2);
        assert.deepEqual(node12.model, {
          id: 12,
          deps: [{id: 122}, {id: 121}]
        });

        assert.deepEqual(node12, node12.children[0].parent);
        assert.deepEqual(node12, node12.children[1].parent);
      });
    });

    describe('addChild()', function () {
      var root;

      beforeEach(function () {
        root = treeModel.parse({id: 1, deps: [{id: 12}, {id: 11}]});
      });

      it('should add child respecting the given comparator', function () {
        root.addChild(treeModel.parse({id: 13}));
        root.addChild(treeModel.parse({id: 10}));
        assert.lengthOf(root.children, 4);
        assert.deepEqual(root.model.deps, [{id: 13}, {id: 12}, {id: 11}, {id: 10}]);
      });
    });
  });
});
<commit_msg>updates tests to illustrate `Array.sort` instability in `parse()`<commit_after>/* global describe, it, beforeEach */

var chai, assert, sinon, spy, TreeModel;
chai = require('chai');
sinon = require('sinon');
spy = sinon.spy;
TreeModel = require('../src/TreeModel');
assert = chai.assert;
chai.Assertion.includeStack = true;

describe('TreeModel', function () {
  'use strict';

  function idEq(id) {
    return function (node) {
      return node.model.id === id;
    };
  }

  describe('with default configuration', function () {
    var treeModel;

    beforeEach(function () {
      treeModel = new TreeModel();
    });

    describe('parse()', function () {
      it('should throw an error when model is a number (not an object)', function () {
        assert.throws(treeModel.parse.bind(treeModel, 1), TypeError, 'Model must be of type object.');
      });

      it('should throw an error when model is a string (not an object)', function () {
        assert.throws(treeModel.parse.bind(treeModel, 'string'), TypeError, 'Model must be of type object.');
      });

      it('should throw an error when some child in the model is not an object', function () {
        assert.throws(
          treeModel.parse.bind(treeModel, {children: ['string']}),
          TypeError,
          'Model must be of type object.');
      });

      it('should create a root node when given a model without children', function () {
        var root;

        root = treeModel.parse({id: 1});

        assert.isUndefined(root.parent);
        assert.isArray(root.children);
        assert.lengthOf(root.children, 0);
        assert.deepEqual(root.model, {id: 1});
      });

      it('should create a root and the respective children when given a model with children', function () {
        var root, node12;

        root = treeModel.parse({
          id: 1,
          children: [
            {
              id: 11,
              children: [{id: 111}]
            },
            {
              id: 12,
              children: [{id: 121}, {id: 122}, {id: 123}, {id: 124}, {id: 125}, {id: 126}, {id: 127}, {id: 128}, {id: 129}]
            }
          ]
        });

        assert.isUndefined(root.parent);
        assert.isArray(root.children);
        assert.lengthOf(root.children, 2);
        assert.deepEqual(root.model, {
          id: 1,
          children: [
            {
              id: 11,
              children: [{id: 111}]
            },
            {
              id: 12,
              children: [{id: 121}, {id: 122}, {id: 123}, {id: 124}, {id: 125}, {id: 126}, {id: 127}, {id: 128}, {id: 129}]
            }
          ]
        });

        assert.deepEqual(root, root.children[0].parent);
        assert.deepEqual(root, root.children[1].parent);

        node12 = root.children[1];
        assert.isArray(node12.children);
        assert.lengthOf(node12.children, 9);
        assert.deepEqual(node12.model, {
          id: 12,
	  children: [{id: 121}, {id: 122}, {id: 123}, {id: 124}, {id: 125}, {id: 126}, {id: 127}, {id: 128}, {id: 129}]
        });

        assert.deepEqual(node12, node12.children[0].parent);
        assert.deepEqual(node12, node12.children[1].parent);
      });
    });

    describe('addChild()', function () {
      var root;

      beforeEach(function () {
        root = treeModel.parse({id: 1, children: [{id: 11}, {id: 12}]});
      });

      it('should add child to the end', function () {
        root.addChild(treeModel.parse({id: 13}));
        root.addChild(treeModel.parse({id: 10}));
        assert.deepEqual(root.model.children, [{id: 11}, {id: 12}, {id: 13}, {id: 10}]);
      });
    });

    describe('getPath()', function () {
      var root;

      beforeEach(function () {
        root = treeModel.parse({
          id: 1,
          children: [
            {
              id: 11,
              children: [{id: 111}]
            },
            {
              id: 12,
              children: [{id: 121}, {id: 122}]
            }
          ]
        });
      });

      it('should get an array with the root node if called on the root node', function () {
        var pathToRoot;
        pathToRoot = root.getPath();
        assert.lengthOf(pathToRoot, 1);
        assert.strictEqual(pathToRoot[0].model.id, 1);
      });

      it('should get an array of nodes from the root to the node (included)', function () {
        var pathToNode121;
        pathToNode121 = root.first(idEq(121)).getPath();
        assert.lengthOf(pathToNode121, 3);
        assert.strictEqual(pathToNode121[0].model.id, 1);
        assert.strictEqual(pathToNode121[1].model.id, 12);
        assert.strictEqual(pathToNode121[2].model.id, 121);
      });
    });

    describe('traversal', function () {
      var root, spy121, spy12;

      function callback121(node) {
        if (node.model.id === 121) {
          return false;
        }
      }

      function callback12(node) {
        if (node.model.id === 12) {
          return false;
        }
      }

      beforeEach(function () {
        root = treeModel.parse({
          id: 1,
          children: [
            {
              id: 11,
              children: [{id: 111}]
            },
            {
              id: 12,
              children: [{id: 121}, {id: 122}]
            }
          ]
        });

        spy121 = sinon.spy(callback121);
        spy12 = sinon.spy(callback12);
      });

      describe('walk depthFirstPreOrder by default', function () {
        it('should traverse the nodes until the callback returns false', function () {
          root.walk(spy121, this);
          assert.strictEqual(spy121.callCount, 5);
          assert(spy121.alwaysCalledOn(this));
          assert(spy121.getCall(0).calledWithExactly(root.first(idEq(1))));
          assert(spy121.getCall(1).calledWithExactly(root.first(idEq(11))));
          assert(spy121.getCall(2).calledWithExactly(root.first(idEq(111))));
          assert(spy121.getCall(3).calledWithExactly(root.first(idEq(12))));
          assert(spy121.getCall(4).calledWithExactly(root.first(idEq(121))));
        });
      });

      describe('walk depthFirstPostOrder', function () {
        it('should traverse the nodes until the callback returns false', function () {
          root.walk({strategy: 'post'}, spy121, this);
          assert.strictEqual(spy121.callCount, 3);
          assert(spy121.alwaysCalledOn(this));
          assert(spy121.getCall(0).calledWithExactly(root.first(idEq(111))));
          assert(spy121.getCall(1).calledWithExactly(root.first(idEq(11))));
          assert(spy121.getCall(2).calledWithExactly(root.first(idEq(121))));
        });
      });

      describe('walk depthFirstPostOrder (2)', function () {
        it('should traverse the nodes until the callback returns false', function () {
          root.walk({strategy: 'post'}, spy12, this);
          assert.strictEqual(spy12.callCount, 5);
          assert(spy12.alwaysCalledOn(this));
          assert(spy12.getCall(0).calledWithExactly(root.first(idEq(111))));
          assert(spy12.getCall(1).calledWithExactly(root.first(idEq(11))));
          assert(spy12.getCall(2).calledWithExactly(root.first(idEq(121))));
          assert(spy12.getCall(3).calledWithExactly(root.first(idEq(122))));
          assert(spy12.getCall(4).calledWithExactly(root.first(idEq(12))));
        });
      });

      describe('walk breadthFirst', function () {
        it('should traverse the nodes until the callback returns false', function () {
          root.walk({strategy: 'breadth'}, spy121, this);
          assert.strictEqual(spy121.callCount, 5);
          assert(spy121.alwaysCalledOn(this));
          assert(spy121.getCall(0).calledWithExactly(root.first(idEq(1))));
          assert(spy121.getCall(1).calledWithExactly(root.first(idEq(11))));
          assert(spy121.getCall(2).calledWithExactly(root.first(idEq(12))));
          assert(spy121.getCall(3).calledWithExactly(root.first(idEq(111))));
          assert(spy121.getCall(4).calledWithExactly(root.first(idEq(121))));
        });
      });

      describe('walk using unknown strategy', function () {
        it('should throw an error warning about the strategy', function () {
          assert.throws(
            root.walk.bind(root, {strategy: 'unknownStrategy'}, callback121, this),
            Error,
            'Unknown tree walk strategy. Valid strategies are \'pre\' [default], \'post\' and \'breadth\'.');
        });
      });
    });

    describe('all()', function () {
      var root;

      beforeEach(function () {
        root = treeModel.parse({
          id: 1,
          children: [
            {
              id: 11,
              children: [{id: 111}]
            },
            {
              id: 12,
              children: [{id: 121}, {id: 122}]
            }
          ]
        });
      });

      it('should get an empty array if no nodes match the predicate', function () {
        var idLt0;
        idLt0 = root.all(function (node) {
          return node.model.id < 0;
        });
        assert.lengthOf(idLt0, 0);
      });

      it('should get an array with the node itself if only the node matches the predicate', function () {
        var idEq1;
        idEq1 = root.all(idEq(1));
        assert.lengthOf(idEq1, 1);
        assert.deepEqual(idEq1[0], root);
      });

      it('should get an array with all nodes that match a given predicate', function () {
        var idGt100;
        idGt100 = root.all(function (node) {
          return node.model.id > 100;
        });
        assert.lengthOf(idGt100, 3);
        assert.strictEqual(idGt100[0].model.id, 111);
        assert.strictEqual(idGt100[1].model.id, 121);
        assert.strictEqual(idGt100[2].model.id, 122);
      });

      it('should get an array with all nodes that match a given predicate (2)', function () {
        var idGt10AndChildOfRoot;
        idGt10AndChildOfRoot = root.all(function (node) {
          return node.model.id > 10 && node.parent === root;
        });
        assert.lengthOf(idGt10AndChildOfRoot, 2);
        assert.strictEqual(idGt10AndChildOfRoot[0].model.id, 11);
        assert.strictEqual(idGt10AndChildOfRoot[1].model.id, 12);
      });
    });

    describe('drop()', function () {
      var root;

      beforeEach(function () {
        root = treeModel.parse({
          id: 1,
          children: [
            {
              id: 11,
              children: [{id: 111}]
            },
            {
              id: 12,
              children: [{id: 121}, {id: 122}]
            }
          ]
        });
      });

      it('should give back the dropped node, even if it is the root', function () {
        assert.deepEqual(root.drop(), root);
      });

      it('should give back the dropped node, which no longer be found in the original root', function () {
        assert.deepEqual(root.first(idEq(11)).drop().model, {id: 11, children: [{id: 111}]});
        assert.isUndefined(root.first(idEq(11)));
      });
    });
  });

  describe('with custom children and comparator', function () {
    var treeModel;

    beforeEach(function () {
      treeModel = new TreeModel({
        childrenPropertyName: 'deps',
        modelComparatorFn: function (a, b) {
          return b.id - a.id;
        }
      });
    });

    describe('parse()', function () {
      it('should create a root and sort the respective children according to the comparator', function () {
        var root, node12;

        root = treeModel.parse({
          id: 1,
          deps: [
            {
              id: 11,
              deps: [{id: 111}]
            },
            {
              id: 12,
              deps: [{id: 121}, {id: 122}]
            }
          ]
        });

        assert.isUndefined(root.parent);
        assert.isArray(root.children);
        assert.lengthOf(root.children, 2);
        assert.deepEqual(root.model, {
          id: 1,
          deps: [
            {
              id: 12,
              deps: [{id: 122}, {id: 121}]
            },
            {
              id: 11,
              deps: [{id: 111}]
            }
          ]
        });

        assert.deepEqual(root, root.children[0].parent);
        assert.deepEqual(root, root.children[1].parent);

        node12 = root.children[0];
        assert.isArray(node12.children);
        assert.lengthOf(node12.children, 2);
        assert.deepEqual(node12.model, {
          id: 12,
          deps: [{id: 122}, {id: 121}]
        });

        assert.deepEqual(node12, node12.children[0].parent);
        assert.deepEqual(node12, node12.children[1].parent);
      });
    });

    describe('addChild()', function () {
      var root;

      beforeEach(function () {
        root = treeModel.parse({id: 1, deps: [{id: 12}, {id: 11}]});
      });

      it('should add child respecting the given comparator', function () {
        root.addChild(treeModel.parse({id: 13}));
        root.addChild(treeModel.parse({id: 10}));
        assert.lengthOf(root.children, 4);
        assert.deepEqual(root.model.deps, [{id: 13}, {id: 12}, {id: 11}, {id: 10}]);
      });
    });
  });
});
<|endoftext|>


<commit_before>var should = require('should');
var request = require('request');
var utils = require('./utils');
var Couch = require('../lib/couch.js');
var testPort = 12500;
var dbName = 'ws_mocks';
var dbConfig = {pathname: dbName};
var serverConfig = {db: dbName, port: testPort};
var newId = '';

// TODO maybe move this to 'before' script
// before script must create couch db and maybe create some new docs there
// after script must remove couchdb
// all test must be independent (don't use results of previous test in next one!)
var Graft = require('graftjs/server');
require('graftjs/middleware/REST.graft.js');
require('../middleware/CouchDB.graft.js');
Graft.load(__dirname);
Graft.start(serverConfig);

function cleanup(done) {
    this.dbDel(function(err) {
        done();
    });
}

// Install and destroy database.
// -----------------------------
describe('install', function() {
    var db = new Couch(dbConfig);

    before(cleanup.bind(db));
    after(cleanup.bind(db));

    it('should install the database', function(done) {
    	utils.install(dbConfig, done);
    });

    it('check that database exists', function(done) {
        db.get('_design/backbone', function(err, doc) {
            if (err) throw err;
            should.ok(doc._rev);
            should.ok(doc.language);
            should.ok(doc.views);
            should.ok(doc.rewrites);
            done();
        });
    });

    it('should delete the database', function(done) {
        db.dbDel(done);
    });

    it('check that database does not exist anymore', function(done) {
        db.get('_design/backbone', function(err, doc) {
            should.deepEqual(err.error, 'not_found');
            done();
        });
    });

});

describe('Reading model', function() {
	describe('Install DB', function() {
		var db = new Couch(dbConfig);

	    before(cleanup.bind(db));

	    it('should install the database', function(done) {
	    	utils.install(dbConfig, done);
	    });
	});

	describe('POST /api/Mock', function() {
		var doc = {
			"id": 'one',
			"someVal": "Ronald McDonald", // was "Emily Baker"
            "favColor": "yello" // new field
		};
		before(utils.requestUrl(testPort, '/api/Mock', 'POST', doc));

		// This is for the new location the server told us to go.
        var newLocation = '';
        it ('should have a location', function() {
            this.resp.should.have.header('Location');
        });

        it ('should return status 303', function() {
            this.resp.should.have.status(303);
        });

        it('response should be json', function() {
            this.resp.should.be.json;
        });

        it ('should have a body', function() {
            should.exist(this.body);
        });
	});

	describe('GET /api/Mock/one', function() {
		before(utils.requestUrl(testPort, '/api/Mock/one'));

		it ('should return status 200', function() {
            this.resp.should.have.status(200);
        });

        it('response should be json', function() {
            this.resp.should.be.json;
        });

        it ('should have a body', function() {
            should.exist(this.body);
        });

        it('should have the correct id', function() {
            this.body.should.have.property('id', 'one');
        });

        it ('should respect the default values', function() {
            this.body.should.have.property('name', 'name');
        });
	});

	describe('destroy DB', function() {
		var db = new Couch(dbConfig);

	    it('should delete the database', function(done) {
	        db.dbDel(done);
	    });
	});
});

// describe('Reading model', function() {
// 	describe('GET /api/Mock/one', function() {
// 		before(utils.requestUrl(testPort, '/api/Mock/one'));

// 		it ('should return status 200', function() {
//             this.resp.should.have.status(200);
//         });

//         it('response should be json', function() {
//             this.resp.should.be.json;
//         });

//         it ('should have a body', function() {
//             should.exist(this.body);
//         });

//         it('should have the correct id', function() {
//             this.body.should.have.property('id', 'one');
//         });

//         it ('should respect the default values', function() {
//             this.body.should.have.property('name', 'name');
//         });
// 	});
// });<commit_msg>remove TODO comment<commit_after>var should = require('should');
var request = require('request');
var utils = require('./utils');
var Couch = require('../lib/couch.js');
var testPort = 12500;
var dbName = 'ws_mocks';
var dbConfig = {pathname: dbName};
var serverConfig = {db: dbName, port: testPort};
var newId = '';

var Graft = require('graftjs/server');
require('graftjs/middleware/REST.graft.js');
require('../middleware/CouchDB.graft.js');
Graft.load(__dirname);
Graft.start(serverConfig);

function cleanup(done) {
    this.dbDel(function(err) {
        done();
    });
}

// Install and destroy database.
// -----------------------------
describe('install', function() {
    var db = new Couch(dbConfig);

    before(cleanup.bind(db));
    after(cleanup.bind(db));

    it('should install the database', function(done) {
    	utils.install(dbConfig, done);
    });

    it('check that database exists', function(done) {
        db.get('_design/backbone', function(err, doc) {
            if (err) throw err;
            should.ok(doc._rev);
            should.ok(doc.language);
            should.ok(doc.views);
            should.ok(doc.rewrites);
            done();
        });
    });

    it('should delete the database', function(done) {
        db.dbDel(done);
    });

    it('check that database does not exist anymore', function(done) {
        db.get('_design/backbone', function(err, doc) {
            should.deepEqual(err.error, 'not_found');
            done();
        });
    });

});

describe('Reading model', function() {
	describe('Install DB', function() {
		var db = new Couch(dbConfig);

	    before(cleanup.bind(db));

	    it('should install the database', function(done) {
	    	utils.install(dbConfig, done);
	    });
	});

	describe('POST /api/Mock', function() {
		var doc = {
			"id": 'one',
			"someVal": "Ronald McDonald", // was "Emily Baker"
            "favColor": "yello" // new field
		};
		before(utils.requestUrl(testPort, '/api/Mock', 'POST', doc));

		// This is for the new location the server told us to go.
        var newLocation = '';
        it ('should have a location', function() {
            this.resp.should.have.header('Location');
        });

        it ('should return status 303', function() {
            this.resp.should.have.status(303);
        });

        it('response should be json', function() {
            this.resp.should.be.json;
        });

        it ('should have a body', function() {
            should.exist(this.body);
        });
	});

	describe('GET /api/Mock/one', function() {
		before(utils.requestUrl(testPort, '/api/Mock/one'));

		it ('should return status 200', function() {
            this.resp.should.have.status(200);
        });

        it('response should be json', function() {
            this.resp.should.be.json;
        });

        it ('should have a body', function() {
            should.exist(this.body);
        });

        it('should have the correct id', function() {
            this.body.should.have.property('id', 'one');
        });

        it ('should respect the default values', function() {
            this.body.should.have.property('name', 'name');
        });
	});

	describe('destroy DB', function() {
		var db = new Couch(dbConfig);

	    it('should delete the database', function(done) {
	        db.dbDel(done);
	    });
	});
});

// describe('Reading model', function() {
// 	describe('GET /api/Mock/one', function() {
// 		before(utils.requestUrl(testPort, '/api/Mock/one'));

// 		it ('should return status 200', function() {
//             this.resp.should.have.status(200);
//         });

//         it('response should be json', function() {
//             this.resp.should.be.json;
//         });

//         it ('should have a body', function() {
//             should.exist(this.body);
//         });

//         it('should have the correct id', function() {
//             this.body.should.have.property('id', 'one');
//         });

//         it ('should respect the default values', function() {
//             this.body.should.have.property('name', 'name');
//         });
// 	});
// });<|endoftext|>


<commit_before>/**
 * Copyright © 2009-2012 A. Matías Quezada
 */

/**
 * A re-implementation of Jasmine (http://pivotal.github.com/jasmine/) just for fun
 *
 * Author:
 *	Seldaiendil <seldaiendil2@gmail.com>
 *	A. Matías Q. <amatiasq@gmail.com>
 *
 * Licence:
 *	Copyright 2010 A. Matías Quezada
 *	This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

(function(global) {
	// Css classes
	var css = {
		'tree': "sassmine",
		'hide': "sassmineHide",
		'suite': "sassmineSuite",
		'spec': "sassmineSpec",
		'fail': "sassmineFailed",
		'errors': "sassmineErrorMessages",
	};

	/*
	 * SassmineClass
	 * Singleton instance 'Sassmine' will be exported
	 * Contains general sassmine structure and references
	 */
	function SassmineClass() {
		this.container = document.createElement("div");
		this.button = document.createElement("button");
		this.tree = new Suite({ dom: this.container }, "", function() { }, false, false);

		this.currentNode = this.tree;
		this.forceShow = false;
		this.suitesCount = 0;
		this.specsCount = 0;

		this.tree.dom.className = css.tree;
		this.button.innerHTML = "Ver Todos";
		this.container.appendChild(this.button);
		this.button.onclick = buttonClickHandler;

		var self = this;
		window.addEventListener("load", function() {
			document.body.appendChild(self.container);
		}, true);
	}
	SassmineClass.prototype.notify = function(message) {
		document.title = message;
	};
	SassmineClass.prototype.fail = function(message) {
		this.currentNode.failed = true;
		this.currentNode.fails.push(message);
	};
	SassmineClass.prototype.createSuite = function(message, handler, hide, isSpec) {
		this.currentNode = new Suite(this.currentNode, message, handler, hide, isSpec);
		this.currentNode.execute();
		this.currentNode = this.currentNode.parent;
	};
	SassmineClass.prototype.describe = function(message, handler, hide) {
		this.suitesCount++;
		this.createSuite(message, handler, hide, false);
		this.notify("Executed " + this.suitesCount + " suites with " + this.specsCount + " specs.");
	};
	SassmineClass.prototype.it = function(message, handler) {
		this.specsCount++;
		this.createSuite(message, handler, false, true);
	};
	SassmineClass.prototype.beforeEach = function(action) {
		this.currentNode.beforeEach = action;
	};
	SassmineClass.prototype.afterEach = function(action) {
		this.currentNode.afterEach = action;
	};
	var Sassmine = new SassmineClass();

	function buttonClickHandler() {
		var divs = Sassmine.container.getElementsByTagName("div");
		for (var i=divs.length; i--; )
			divs[i].className = divs[i].className.replace(css.hide, "");
	};

	/*
	 * Suite
	 * Private class
	 * Provides a class to handle 'describe' and 'it' functions
	 */
	function Suite(parent, message, handler, hide, isSpec) {
		this.dom = document.createElement("div");
		this.message = message;
		this.handler = handler;
		this.failed = false;
		this.hide = hide;
		this.fails = [];

		this.beforeEach = null;
		this.afterEach = null;
		this.parent = parent;
		this.suites = [];
		this.specs = [];

		if (typeof parent.parent !== 'undefined')
			parent[isSpec ? 'specs' : 'suites'].push(this);
		parent.dom.appendChild(this.dom);
		this.dom.className = isSpec ? css.spec : css.suite;
		this.dom.innerHTML = message;
	}
	Suite.prototype.execute = function() {
		if (this.parent.beforeEach)
			this.parent.beforeEach();

		try {
			var result = this.handler.call(null);
		} catch(ex) {
			this.failed = true;
			this.fails.push(ex.message);
		}

		if (this.failed) {
			this.parent.failed = true;
			this.dom.className += " " + css.fail;
			if (this.fails.length > 0) {
				var messages = document.createElement('div');
				messages.className = css.errors;
				messages.innerHTML = this.fails.join("
");
				this.dom.appendChild(messages);
			}
		} else if (this.hide && !Sassmine.forceShow) {
			this.dom.className += " " + css.hide;
		}

		if (this.parent.afterEach)
			this.parent.afterEach();
	};

	/*
	 * Spy
	 * Public class, will be exported
	 * Provides a spy function than intercepts a function call and registrates scope, arguments and call counts
	 */
	function Spy(original, callOriginal) {
		this.reset();
		this.newSpy();
		this.original = original;
		this.callOriginal = callOriginal;
	}
	Spy.spyMethod = function(instance, method, callOriginal) {
		var spy = new Spy(instance[method], callOriginal)
		instance[method] = spy.spy;
		return spy;
	};
	Spy.prototype.reset = function() {
		this.callCount = 0;
		this.scopes = [];
		this.arguments = [];
		this.lastScope = null;
		this.lastArguments = [];
	};
	Spy.prototype.newSpy = function() {
		var self = this;
		this.spy = function() {
			self.callCount++;
			self.scopes.push(this);
			var args = [];
			for (var i=0, len=arguments.length; i<len; i++)
				args.push(arguments[i]);
			self.arguments.push(args);
			self.lastScope = this;
			self.lastArguments = args;
			if (self.callOriginal)
				self.original.apply(this, arguments);
		};
	};

	/*
	 * Expectations
	 * Private class
	 * Instances of this class will be returned when call expect() function
	 * Each expectation instance has a subinstance 'not', than reverses the result
	 */
	function Expectation(target, not) {
		this.target = target;
		// If this isn't the "not" expectation it must create one
		this.isNot = typeof not !== 'undefined';
		if (!this.isNot)
			this.not = new Expectation(target, true);
	}
	Expectation.prototype.test = function(bool, message) {
		if (bool !== this.isNot)
			return true;
		Sassmine.fail(message.replace("[NOT] ", this.isNot ? "not " : ""));
		return false;
	};
	Expectation.prototype.printObject = function(object) {
		return "--[" + object + "]-- (" + (typeof object) + ")"
	};
	Expectation.prototype.standardMessage = function(target, text, objetive) {
		var end = typeof objetive !== 'undefined' ? " " + this.printObject(objetive) : "";
		return "Expected " + this.printObject(this.target) + " " + text + end;
	};

	// Comparison expectations
	Expectation.prototype.toBe = function(objetive) {
		return this.test(this.target === objetive, this.standardMessage(this.target, "to [NOT] be", objetive));
	};
	Expectation.prototype.toBeLike = function(objetive) {
		return this.test(this.target == objetive, this.standardMessage(this.target, "to [NOT] be like", objetive));
	};
	Expectation.prototype.toBeTrue = function() {
		return this.test(this.target === true, this.standardMessage(this.target, "to [NOT] be", true));
	};
	Expectation.prototype.toBeFalse = function() {
		return this.test(this.target === false, this.standardMessage(this.target, "to [NOT] be", false));
	};
	Expectation.prototype.toBeTruthy = function() {
		return this.test(!!this.target, this.standardMessage(this.target, "to [NOT] be truthy"));
	};
	Expectation.prototype.toBeFalsy = function() {
		return this.test(!this.target, this.standardMessage(this.target, "to [NOT] be falsy"));
	};
	Expectation.prototype.toBeNull = function() {
		return this.test(this.target === null, this.standardMessage(this.target, "to [NOT] be", null));
	};
	Expectation.prototype.toBeUndefined = function() {
		return this.test(typeof this.target === 'undefined',
			this.standardMessage(this.target, "to [NOT] be undefined"));
	};
	Expectation.prototype.toBeNaN = function() {
		return this.test(isNaN(this.target), this.standardMessage(this.target, "to [NOT] be", NaN));
	};

	// Numeric expectations
	Expectation.prototype.toBeBetween = function(val1, val2) {
		return this.test(this.target >= Math.min(val1, val2) && this.target <= Math.max(val1, val2),
			"Expected " + this.printObject(this.target) + " to [NOT] be between " +
				this.printObject(val1) + " and " + this.printObject(val2));
	};
	Expectation.prototype.toBeLowerThan = function(num) {
		return this.test(this.target < num, this.standardMessage(this.target, "to [NOT] be lower than", num));
	};
	Expectation.prototype.toBeBiggerThan = function(num) {
		return this.test(this.target > num, this.standardMessage(this.target, "to [NOT] be bigger than", num));
	};
	Expectation.prototype.toBePositive = function() {
		return this.test(this.target > 0, this.standardMessage(this.target, "to [NOT] be positive"));
	};
	Expectation.prototype.toBeNegative = function() {
		return this.test(this.target < 0, this.standardMessage(this.target, "to [NOT] be negative"));
	};

	// Class expectations
	Expectation.prototype.toBeArray = function() {
		return this.test(Object.prototype.toString.call(this.target) === "[object Array]",
			this.standardMessage(this.target, "to [NOT] be a array"));
	};
	Expectation.prototype.toBeFunction = function() {
		return this.test(this.target instanceof Function, this.standardMessage(this.target, "to [NOT] be a function"));
	};
	Expectation.prototype.toBeInstanceOf = function(targetClass) {
		return this.test(this.target instanceof targetClass,
			this.standardMessage(this.target, "to [NOT] be instance of", targetClass));
	};
	Expectation.prototype.toHaveProperty = function(propertyName) {
		return this.test(propertyName in this.target,
			this.standardMessage(this.target, "to [NOT] have property --[" + propertyName + "]--"));
	};

	// Error manage expectations
	Expectation.prototype.toThrowError = function() {
		if (!(this.target instanceof Function))
			throw new Error("Target is not a function");
		try {
			this.target.call(global);
			return this.test(false, "Expected --[" + this.target + "]-- to [NOT] throw a exception");
		} catch (ex) {
			return this.test(true,
				"Expected --[" + this.target + "]-- to [NOT] throw error but --["
				+ ex + "]-- thrown with message --[" + ex.message + "]--");
		}
	};
	Expectation.prototype.toThrow = function(errorClass) {
		if (!(this.target instanceof Function))
			throw new Error("Target is not a function");
		try {
			this.target.call(global);
			return this.test(false, "Expected --[" + this.target + "]-- to [NOT] throw a exception");
		} catch (ex) {
			return this.test(ex instanceof errorClass,
				"Expected --[" + this.target + "]-- to [NOT] throw --[" + errorClass +
				"]-- but --[" + ex + "]-- thrown");
		}
	};

	// Export to global scope
	global.Spy = Spy;
	global.Sassmine = Sassmine;
	global.expect = function(target) {
		return new Expectation(target);
	};
	global.xdescribe = function() { };
	global.describe = function(message, action, hide) {
		Sassmine.describe(message, action, hide);
	};
	global.xit = function() { };
	global.it = function(message, action) {
		Sassmine.it(message, action);
	};
	global.beforeEach = function(action) {
		Sassmine.beforeEach(action);
	};
	global.afterEach = function(action) {
		Sassmine.afterEach(action);
	};
})(this);<commit_msg>Starting develop<commit_after>/**
 * Copyright © 2009-2012 A. Matías Quezada
 */
/**
 * A re-implementation of Jasmine (http://pivotal.github.com/jasmine/) just for fun
 *
 * Author:
 *	Seldaiendil <seldaiendil2@gmail.com>
 *	A. Matías Q. <amatiasq@gmail.com>
 */

(function(global) {

	function SassmineClass() {

	}
	SassmineClass.prototype = {
		constructor: SassmineClass,

		notify: function() { },
		fail: function() { },
		suite: function() { },
		test: function() { },
		expectation: function() { }
	};

	global.sas = {

	};

})(this);

(function(global) {
	// Css classes
	var css = {
		'tree': "sassmine",
		'hide': "sassmineHide",
		'suite': "sassmineSuite",
		'spec': "sassmineSpec",
		'fail': "sassmineFailed",
		'errors': "sassmineErrorMessages",
	};

	/*
	 * SassmineClass
	 * Singleton instance 'Sassmine' will be exported
	 * Contains general sassmine structure and references
	 */
	function SassmineClass() {
		this.container = document.createElement("div");
		this.button = document.createElement("button");
		this.tree = new Suite({ dom: this.container }, "", function() { }, false, false);

		this.currentNode = this.tree;
		this.forceShow = false;
		this.suitesCount = 0;
		this.specsCount = 0;

		this.tree.dom.className = css.tree;
		this.button.innerHTML = "Ver Todos";
		this.container.appendChild(this.button);
		this.button.onclick = buttonClickHandler;

		var self = this;
		window.addEventListener("load", function() {
			document.body.appendChild(self.container);
		}, true);
	}
	SassmineClass.prototype.notify = function(message) {
		document.title = message;
	};
	SassmineClass.prototype.fail = function(message) {
		this.currentNode.failed = true;
		this.currentNode.fails.push(message);
	};
	SassmineClass.prototype.createSuite = function(message, handler, hide, isSpec) {
		this.currentNode = new Suite(this.currentNode, message, handler, hide, isSpec);
		this.currentNode.execute();
		this.currentNode = this.currentNode.parent;
	};
	SassmineClass.prototype.describe = function(message, handler, hide) {
		this.suitesCount++;
		this.createSuite(message, handler, hide, false);
		this.notify("Executed " + this.suitesCount + " suites with " + this.specsCount + " specs.");
	};
	SassmineClass.prototype.it = function(message, handler) {
		this.specsCount++;
		this.createSuite(message, handler, false, true);
	};
	SassmineClass.prototype.beforeEach = function(action) {
		this.currentNode.beforeEach = action;
	};
	SassmineClass.prototype.afterEach = function(action) {
		this.currentNode.afterEach = action;
	};
	var Sassmine = new SassmineClass();

	function buttonClickHandler() {
		var divs = Sassmine.container.getElementsByTagName("div");
		for (var i=divs.length; i--; )
			divs[i].className = divs[i].className.replace(css.hide, "");
	};

	/*
	 * Suite
	 * Private class
	 * Provides a class to handle 'describe' and 'it' functions
	 */
	function Suite(parent, message, handler, hide, isSpec) {
		this.dom = document.createElement("div");
		this.message = message;
		this.handler = handler;
		this.failed = false;
		this.hide = hide;
		this.fails = [];

		this.beforeEach = null;
		this.afterEach = null;
		this.parent = parent;
		this.suites = [];
		this.specs = [];

		if (typeof parent.parent !== 'undefined')
			parent[isSpec ? 'specs' : 'suites'].push(this);
		parent.dom.appendChild(this.dom);
		this.dom.className = isSpec ? css.spec : css.suite;
		this.dom.innerHTML = message;
	}
	Suite.prototype.execute = function() {
		if (this.parent.beforeEach)
			this.parent.beforeEach();

		try {
			var result = this.handler.call(null);
		} catch(ex) {
			this.failed = true;
			this.fails.push(ex.message);
		}

		if (this.failed) {
			this.parent.failed = true;
			this.dom.className += " " + css.fail;
			if (this.fails.length > 0) {
				var messages = document.createElement('div');
				messages.className = css.errors;
				messages.innerHTML = this.fails.join("
");
				this.dom.appendChild(messages);
			}
		} else if (this.hide && !Sassmine.forceShow) {
			this.dom.className += " " + css.hide;
		}

		if (this.parent.afterEach)
			this.parent.afterEach();
	};

	/*
	 * Spy
	 * Public class, will be exported
	 * Provides a spy function than intercepts a function call and registrates scope, arguments and call counts
	 */
	function Spy(original, callOriginal) {
		this.reset();
		this.newSpy();
		this.original = original;
		this.callOriginal = callOriginal;
	}
	Spy.spyMethod = function(instance, method, callOriginal) {
		var spy = new Spy(instance[method], callOriginal)
		instance[method] = spy.spy;
		return spy;
	};
	Spy.prototype.reset = function() {
		this.callCount = 0;
		this.scopes = [];
		this.arguments = [];
		this.lastScope = null;
		this.lastArguments = [];
	};
	Spy.prototype.newSpy = function() {
		var self = this;
		this.spy = function() {
			self.callCount++;
			self.scopes.push(this);
			var args = [];
			for (var i=0, len=arguments.length; i<len; i++)
				args.push(arguments[i]);
			self.arguments.push(args);
			self.lastScope = this;
			self.lastArguments = args;
			if (self.callOriginal)
				self.original.apply(this, arguments);
		};
	};

	/*
	 * Expectations
	 * Private class
	 * Instances of this class will be returned when call expect() function
	 * Each expectation instance has a subinstance 'not', than reverses the result
	 */
	function Expectation(target, not) {
		this.target = target;
		// If this isn't the "not" expectation it must create one
		this.isNot = typeof not !== 'undefined';
		if (!this.isNot)
			this.not = new Expectation(target, true);
	}
	Expectation.prototype.test = function(bool, message) {
		if (bool !== this.isNot)
			return true;
		Sassmine.fail(message.replace("[NOT] ", this.isNot ? "not " : ""));
		return false;
	};
	Expectation.prototype.printObject = function(object) {
		return "--[" + object + "]-- (" + (typeof object) + ")"
	};
	Expectation.prototype.standardMessage = function(target, text, objetive) {
		var end = typeof objetive !== 'undefined' ? " " + this.printObject(objetive) : "";
		return "Expected " + this.printObject(this.target) + " " + text + end;
	};

	// Comparison expectations
	Expectation.prototype.toBe = function(objetive) {
		return this.test(this.target === objetive, this.standardMessage(this.target, "to [NOT] be", objetive));
	};
	Expectation.prototype.toBeLike = function(objetive) {
		return this.test(this.target == objetive, this.standardMessage(this.target, "to [NOT] be like", objetive));
	};
	Expectation.prototype.toBeTrue = function() {
		return this.test(this.target === true, this.standardMessage(this.target, "to [NOT] be", true));
	};
	Expectation.prototype.toBeFalse = function() {
		return this.test(this.target === false, this.standardMessage(this.target, "to [NOT] be", false));
	};
	Expectation.prototype.toBeTruthy = function() {
		return this.test(!!this.target, this.standardMessage(this.target, "to [NOT] be truthy"));
	};
	Expectation.prototype.toBeFalsy = function() {
		return this.test(!this.target, this.standardMessage(this.target, "to [NOT] be falsy"));
	};
	Expectation.prototype.toBeNull = function() {
		return this.test(this.target === null, this.standardMessage(this.target, "to [NOT] be", null));
	};
	Expectation.prototype.toBeUndefined = function() {
		return this.test(typeof this.target === 'undefined',
			this.standardMessage(this.target, "to [NOT] be undefined"));
	};
	Expectation.prototype.toBeNaN = function() {
		return this.test(isNaN(this.target), this.standardMessage(this.target, "to [NOT] be", NaN));
	};

	// Numeric expectations
	Expectation.prototype.toBeBetween = function(val1, val2) {
		return this.test(this.target >= Math.min(val1, val2) && this.target <= Math.max(val1, val2),
			"Expected " + this.printObject(this.target) + " to [NOT] be between " +
				this.printObject(val1) + " and " + this.printObject(val2));
	};
	Expectation.prototype.toBeLowerThan = function(num) {
		return this.test(this.target < num, this.standardMessage(this.target, "to [NOT] be lower than", num));
	};
	Expectation.prototype.toBeBiggerThan = function(num) {
		return this.test(this.target > num, this.standardMessage(this.target, "to [NOT] be bigger than", num));
	};
	Expectation.prototype.toBePositive = function() {
		return this.test(this.target > 0, this.standardMessage(this.target, "to [NOT] be positive"));
	};
	Expectation.prototype.toBeNegative = function() {
		return this.test(this.target < 0, this.standardMessage(this.target, "to [NOT] be negative"));
	};

	// Class expectations
	Expectation.prototype.toBeArray = function() {
		return this.test(Object.prototype.toString.call(this.target) === "[object Array]",
			this.standardMessage(this.target, "to [NOT] be a array"));
	};
	Expectation.prototype.toBeFunction = function() {
		return this.test(this.target instanceof Function, this.standardMessage(this.target, "to [NOT] be a function"));
	};
	Expectation.prototype.toBeInstanceOf = function(targetClass) {
		return this.test(this.target instanceof targetClass,
			this.standardMessage(this.target, "to [NOT] be instance of", targetClass));
	};
	Expectation.prototype.toHaveProperty = function(propertyName) {
		return this.test(propertyName in this.target,
			this.standardMessage(this.target, "to [NOT] have property --[" + propertyName + "]--"));
	};

	// Error manage expectations
	Expectation.prototype.toThrowError = function() {
		if (!(this.target instanceof Function))
			throw new Error("Target is not a function");
		try {
			this.target.call(global);
			return this.test(false, "Expected --[" + this.target + "]-- to [NOT] throw a exception");
		} catch (ex) {
			return this.test(true,
				"Expected --[" + this.target + "]-- to [NOT] throw error but --["
				+ ex + "]-- thrown with message --[" + ex.message + "]--");
		}
	};
	Expectation.prototype.toThrow = function(errorClass) {
		if (!(this.target instanceof Function))
			throw new Error("Target is not a function");
		try {
			this.target.call(global);
			return this.test(false, "Expected --[" + this.target + "]-- to [NOT] throw a exception");
		} catch (ex) {
			return this.test(ex instanceof errorClass,
				"Expected --[" + this.target + "]-- to [NOT] throw --[" + errorClass +
				"]-- but --[" + ex + "]-- thrown");
		}
	};

	// Export to global scope
	global.Spy = Spy;
	global.Sassmine = Sassmine;
	global.expect = function(target) {
		return new Expectation(target);
	};
	global.xdescribe = function() { };
	global.describe = function(message, action, hide) {
		Sassmine.describe(message, action, hide);
	};
	global.xit = function() { };
	global.it = function(message, action) {
		Sassmine.it(message, action);
	};
	global.beforeEach = function(action) {
		Sassmine.beforeEach(action);
	};
	global.afterEach = function(action) {
		Sassmine.afterEach(action);
	};
})(this);
<|endoftext|>


<commit_before>#!/usr/local/bin/node

var request = require('request');
var fs = require('fs');
var os = require('os');
var guid = require('guid');

module.exports = {};

module.exports.sdurl = function(path) {
	var url = module.exports.host + "2" + path + "?accessToken=" + module.exports.user.accessToken;
	return url;
};

var savvydox = module.exports;

module.exports.login = function(host, login, password, completionHandler, errorHandler) {
	savvydox.host = host;

	request.post(module.exports.host + "2/login", {
		'auth': { 'user': login, 'pass': password, 'sendImmediately': true } }, function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		savvydox.user = JSON.parse(body);

		completionHandler(JSON.parse(body));
	});
};

module.exports.postDocument = function(document, contentPath, sourcePath, completionHandler, errorHandler) {
	var docurl = savvydox.sdurl("/documents/" + document.id);
	request(docurl, function(error, response, body) {
		var formData = {
			document: JSON.stringify(document),
		};

		if (contentPath) {
			formData.content = {
				value: 	fs.createReadStream(contentPath),
				options: {
					filename: 'content.pdf',
					contentType: 'application/pdf'
				}
			};
		}

		if (sourcePath) {
			formData.source = {
				value: 	fs.createReadStream(sourcePath),
				options: {
					filename: document.sourceFileName,
					contentType: document.source.contentType
				}
			};
		}

		request.post({url: docurl, formData: formData}, function(error, response, body) {
			if (error) {
				if (errorHandler) {
					errorHandler(error);
				}
				return;
			}

			var newdoc = JSON.parse(body);
			completionHandler(newdoc);
		});
	});
};

// To attach source, pass in sourceInfo that has path, fileName, and contentType properties
module.exports.postNewDocument = function(document, contentPath, sourceInfo, completionHandler, errorHandler) {
	var formData = {
		document: JSON.stringify(document),
		content: {
			value: 	fs.createReadStream(contentPath),
			options: {
				filename: 'content.pdf',
				contentType: 'application/pdf'
			}
		}
	};

	if (sourceInfo) {
		formData.source = {
			value: 	fs.createReadStream(source.path),
			options: {
				filename: source.fileName,
				contentType: source.contentType
			}
		};
	}

	request.post({url: savvydox.sdurl("/documents"), formData: formData}, function(error, response, body) {
		if (error) {
			errorHandler(error);
			return;
		}

		newdoc = JSON.parse(body);
		completionHandler(newdoc);
	});
};

module.exports.downloadDocumentContent = function(document, path, completionHandler, errorHandler) {
	var contenturl = savvydox.sdurl("/documents/" + document.id + "/content");
	var contentpath = path + "/content.pdf";
	var file = fs.createWriteStream(contentpath)
	var req = request(contenturl).pipe(file);
	file.on('finish', function() {
		// If the document has source associated with it, we need to download that
		if (document.hasOwnProperty("source")) {
			// Download source
			var srcurl = savvydox.sdurl("/documents/" + document.id + "/source");

			var srcfn = "content.docx";
			if (document.sourceFileName && document.sourceFileName.endsWith(".docx")) {
				srcfn = document.sourceFileName;
			}

			var srcdest = path.name + "/" + srcfn;
			var srcfile = fs.createWriteStream(srcdest)
			var srcreq = request(srcurl).pipe(srcfile);
			srcfile.on('finish', function() {
				completionHandler(contentpath, srcdest);
			});
		} else {
			completionHandler(contentpath);
		}
	});
};

module.exports.getUser = function(userid, completionHandler, errorHandler) {
	var meurl = savvydox.sdurl("/users/" + userid);

	// Part one - gather information including the user, event, and document that we're working with
	request(meurl, function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		var user = JSON.parse(body);
		completionHandler(user);
	});
};

module.exports.getEvent = function(eventid, completionHandler, errorHandler) {
	request(eventurl, function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		var events = JSON.parse(body);
		var event = events.events[0];
		completionHandler(event);
	});
};

module.exports.getDocument = function(documentid, completionHandler, errorHandler) {
	var docurl = savvydox.sdurl("/documents/" + documentid);
	request(docurl, function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		var document = JSON.parse(body);
		completionHandler(document);
	});
};

module.exports.getCollections = function(completionHandler, errorHandler) {
	request(savvydox.sdurl("/collections"), function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		var collections = JSON.parse(body);
		completionHandler(collections);
	});
};

module.exports.getDocumentRecipients = function(documentid, completionHandler, errorHandler) {
	var recipurl = savvydox.sdurl("/documents/" + event.payload.document + "/recipients");
	recipurl += "&format=decompose";
	request(recipurl, function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		var recipients = JSON.parse(body);
		return recipients;
	});
};

module.exports.getDocumentTasks = function(documentid, completionHandler, errorHandler) {
	var tasksurl = savvydox.sdurl("/usertasks/document/" + event.payload.document);
	tasksurl += "&format=decompose";
	console.log("Requesting tasks: " + tasksurl);

	request(tasksurl, function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		var tasks = JSON.parse(body);
		return tasks;
	});
}
<commit_msg>Fixes incorrect path when downloading document source<commit_after>#!/usr/local/bin/node

var request = require('request');
var fs = require('fs');
var os = require('os');
var guid = require('guid');

module.exports = {};

module.exports.sdurl = function(path) {
	var url = module.exports.host + "2" + path + "?accessToken=" + module.exports.user.accessToken;
	return url;
};

var savvydox = module.exports;

module.exports.login = function(host, login, password, completionHandler, errorHandler) {
	savvydox.host = host;

	request.post(module.exports.host + "2/login", {
		'auth': { 'user': login, 'pass': password, 'sendImmediately': true } }, function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		savvydox.user = JSON.parse(body);

		completionHandler(JSON.parse(body));
	});
};

module.exports.postDocument = function(document, contentPath, sourcePath, completionHandler, errorHandler) {
	var docurl = savvydox.sdurl("/documents/" + document.id);
	request(docurl, function(error, response, body) {
		var formData = {
			document: JSON.stringify(document),
		};

		if (contentPath) {
			formData.content = {
				value: 	fs.createReadStream(contentPath),
				options: {
					filename: 'content.pdf',
					contentType: 'application/pdf'
				}
			};
		}

		if (sourcePath) {
			formData.source = {
				value: 	fs.createReadStream(sourcePath),
				options: {
					filename: document.sourceFileName,
					contentType: document.source.contentType
				}
			};
		}

		request.post({url: docurl, formData: formData}, function(error, response, body) {
			if (error) {
				if (errorHandler) {
					errorHandler(error);
				}
				return;
			}

			var newdoc = JSON.parse(body);
			completionHandler(newdoc);
		});
	});
};

// To attach source, pass in sourceInfo that has path, fileName, and contentType properties
module.exports.postNewDocument = function(document, contentPath, sourceInfo, completionHandler, errorHandler) {
	var formData = {
		document: JSON.stringify(document),
		content: {
			value: 	fs.createReadStream(contentPath),
			options: {
				filename: 'content.pdf',
				contentType: 'application/pdf'
			}
		}
	};

	if (sourceInfo) {
		formData.source = {
			value: 	fs.createReadStream(source.path),
			options: {
				filename: source.fileName,
				contentType: source.contentType
			}
		};
	}

	request.post({url: savvydox.sdurl("/documents"), formData: formData}, function(error, response, body) {
		if (error) {
			errorHandler(error);
			return;
		}

		newdoc = JSON.parse(body);
		completionHandler(newdoc);
	});
};

module.exports.downloadDocumentContent = function(document, path, completionHandler, errorHandler) {
	var contenturl = savvydox.sdurl("/documents/" + document.id + "/content");
	var contentpath = path + "/content.pdf";
	var file = fs.createWriteStream(contentpath)
	var req = request(contenturl).pipe(file);
	file.on('finish', function() {
		// If the document has source associated with it, we need to download that
		if (document.hasOwnProperty("source")) {
			// Download source
			var srcurl = savvydox.sdurl("/documents/" + document.id + "/source");

			var srcfn = "content.docx";
			if (document.sourceFileName && document.sourceFileName.endsWith(".docx")) {
				srcfn = document.sourceFileName;
			}

			var srcdest = path + "/" + srcfn;
			var srcfile = fs.createWriteStream(srcdest)
			var srcreq = request(srcurl).pipe(srcfile);
			srcfile.on('finish', function() {
				completionHandler(contentpath, srcdest);
			});
		} else {
			completionHandler(contentpath);
		}
	});
};

module.exports.getUser = function(userid, completionHandler, errorHandler) {
	var meurl = savvydox.sdurl("/users/" + userid);

	// Part one - gather information including the user, event, and document that we're working with
	request(meurl, function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		var user = JSON.parse(body);
		completionHandler(user);
	});
};

module.exports.getEvent = function(eventid, completionHandler, errorHandler) {
	request(eventurl, function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		var events = JSON.parse(body);
		var event = events.events[0];
		completionHandler(event);
	});
};

module.exports.getDocument = function(documentid, completionHandler, errorHandler) {
	var docurl = savvydox.sdurl("/documents/" + documentid);
	request(docurl, function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		var document = JSON.parse(body);
		completionHandler(document);
	});
};

module.exports.getCollections = function(completionHandler, errorHandler) {
	request(savvydox.sdurl("/collections"), function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		var collections = JSON.parse(body);
		completionHandler(collections);
	});
};

module.exports.getDocumentRecipients = function(documentid, completionHandler, errorHandler) {
	var recipurl = savvydox.sdurl("/documents/" + event.payload.document + "/recipients");
	recipurl += "&format=decompose";
	request(recipurl, function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		var recipients = JSON.parse(body);
		return recipients;
	});
};

module.exports.getDocumentTasks = function(documentid, completionHandler, errorHandler) {
	var tasksurl = savvydox.sdurl("/usertasks/document/" + event.payload.document);
	tasksurl += "&format=decompose";
	console.log("Requesting tasks: " + tasksurl);

	request(tasksurl, function(error, response, body) {
		if (error || response.statusCode >= 400) {
			if (errorHandler) {
				errorHandler(error);
			}
			return;
		}

		var tasks = JSON.parse(body);
		return tasks;
	});
}
<|endoftext|>