<commit_before>import nock from 'nock'
import es6promise from 'es6-promise'

import quickrest from '../src'

const PromiseLib = es6promise.Promise

describe('quickrest', function () {
  const root = 'https://api.example.com'
  const endpoints = [
    'users',
    'users/posts',
    'users/posts/comments',
    'posts',
    'posts/comments',
    'comments',
  ]

  it('is a function', () => {
    expect(quickrest).to.be.a('function')
  })

  it('throws an error if `endpoints` is undefined or an empty array', () => {
    const fn = function () { quickrest({root}) }
    expect(fn).to.throw(/endpoints .* non-empty/)
  })

  it('throws an error if `root` is falsy', () => {
    const fn = function () { quickrest({endpoints}) }
    const gn = function () { quickrest({endpoints, root: ''}) }
    const hn = function () { quickrest({endpoints, root: '  '}) }
    expect(fn).to.throw(/required/)
    expect(gn).to.throw(/required/)
    expect(hn).to.throw(/required/)
  })

  let spy
  let api

  beforeEach(() => {
    spy = sinon.spy()
    api = quickrest({root, endpoints, request: spy})
  })

  it('should return a function', () => {
    expect(api).to.be.a('function')
  })

  it('that does not have any REST methods attached', () => {
    expect(api).to.not.have.property('create')
    expect(api).to.not.have.property('get')
    expect(api).to.not.have.property('del')
    expect(api).to.not.have.property('delete')
    expect(api).to.not.have.property('update')
  })

  it('should have top level resources', () => {
    expect(api).to.have.property('users')
    expect(api).to.have.property('posts')
    expect(api).to.have.property('comments')
  })

  it('and inaccessible subresources', () => {
    expect(api).to.not.have.property('users.posts')
    expect(api).to.not.have.property('posts.comments')
  })

  let spy1
  beforeEach(() => {
    spy1 = sinon.spy()
  })

  describe('top-level resources', () => {
    it('urls are prefixed only be root', () => {
      const args = {}
      api.users.create({}, spy1)
      expect(spy).to.have.been.calledWith(`${root}/users`, 'post', args)
    })

    it('have a "get" method that includes resource id', () => {
      api.users(9000).get(spy1)
      expect(spy).to.have.been.calledWith(`${root}/users/9000`, 'get')
    })

    it('as does "del"', () => {
      api.users(9000).del(spy1)
      expect(spy).to.have.been.calledWith(`${root}/users/9000`, 'delete')
    })

    it('and "update"', () => {
      const args = {}
      api.users(9000).update(args, spy1)
      expect(spy).to.have.been.calledWith(`${root}/users/9000`, 'put', args)
    })
  })

  describe('subresources', () => {
    it('include their parent resource\'s fragment in their path', () => {
      const spy2 = sinon.spy()
      const args = {}
      api.users(9000).posts.create(args, spy1)
      expect(spy).to.have.been.calledWith(`${root}/users/9000/posts`, 'post', args)

      api.users(9000).posts(3).comments.create(args, spy2)
      expect(spy).to.have.been.calledWith(`${root}/users/9000/posts/3/comments`, 'post', args)
    })
  })

  describe('request', () => {
    beforeEach(() => {
      api = quickrest({root, endpoints})
    })

    it('may return a promise with response data', () => {
      const body = {
        id: 9000,
        email: 'jane.smith@example.com',
      }

      nock(root)
        .get('/users/9000')
        .reply(200, body)

      const promise = api.users(9000).get()

      return PromiseLib.all([
        expect(promise).to.eventually.have.property('model').that.eql(body),
        expect(promise).to.eventually.have.property('status', 200),
      ])
    })

    it('for post', () => {
      const body = {
        title: 'blog post',
        content: 'this is great',
      }

      nock(root)
        .post('/users/9000/posts')
        .reply(200, body)

      const promise = api.users(9000).posts.create(body)

      return PromiseLib.all([
        expect(promise).to.eventually.have.property('model').that.eql(body),
        expect(promise).to.eventually.have.property('status', 200),
      ])
    })

    it('for put', () => {
      const body = {
        title: 'blog post',
        content: 'this is great',
      }

      const resp = Object.assign({id: 4}, body)

      nock(root)
        .put('/users/9000/posts', body)
        .reply(200, resp)

      const promise = api.users(9000).posts.update(body)

      return PromiseLib.all([
        expect(promise).to.eventually.have.property('model').that.eql(resp),
        expect(promise).to.eventually.have.property('status', 200),
      ])
    })

    it('get all', () => {
      const query = {
        page: 2,
        rpp: 50,
      }

      const resp = {
        rpp: query.rpp,
        page: 2,
        items: []
      }

      nock(root)
        .get('/users/9000/posts')
        .query(query)
        .reply(200, resp)

      const promise = api.users(9000).posts.list(query)

      return PromiseLib.all([
        expect(promise).to.eventually.have.property('model').that.eql(resp),
        expect(promise).to.eventually.have.property('status', 200),
      ])
    })

    it('and delete', () => {
      nock(root)
        .delete('/users/9000')
        .reply(204)

      const promise = api.users(9000).del()

      return PromiseLib.all([
        expect(promise).to.eventually.have.property('status', 204),
      ])
    })

    it('may return a reject promise if the request fails', () => {
      nock(root)
        .delete('/users/9001')
        .reply(404)

      const promise = api.users(9001).del()

      return PromiseLib.all([
        expect(promise).to.be.rejected
      ])
    })

    it('invokes a callback with response data', (done) => {
      const body = {
        id: 9000,
        email: 'jane.smith@example.com',
      }

      nock(root)
        .get('/users/9000')
        .reply(200, body)

      api.users(9000).get((err, res) => {
        if (err) return done(err)
        expect(res.model).to.eql(body)
        done()
      })
    })

    it('invokes a callback with error data if the request fails', done => {
      const body = {
        id: 9000,
        email: 'jane.smith@example.com',
      }

      nock(root)
        .get('/users/9000')
        .reply(404, body)

      api.users(9000).get((err, res) => {
        expect(err).to.exist.be.an.instanceOf(Error)
        expect(res.status).to.equal(404)
        done()
      })
    })
  })

  describe('versions', () => {
    it('allows you to gracefully evolve an API', () => {
      api = quickrest({endpoints, root, versions: 'v1'})
      expect(api.v1).to.exist
      expect(api.v1().users).to.exist
    })
  })
})
<commit_msg>additional tests<commit_after>import nock from 'nock'
import es6promise from 'es6-promise'

import quickrest from '../src'

const PromiseLib = es6promise.Promise

describe('quickrest', function () {
  const root = 'https://api.example.com'
  const endpoints = [
    'users',
    'users/posts',
    'users/posts/comments',
    'posts',
    'posts/comments',
    'comments',
  ]

  it('is a function', () => {
    expect(quickrest).to.be.a('function')
  })

  it('throws an error if `endpoints` is undefined or an empty array', () => {
    const fn = function () { quickrest({root}) }
    expect(fn).to.throw(/endpoints .* non-empty/)
  })

  it('throws an error if `root` is falsy', () => {
    const fn = function () { quickrest({endpoints}) }
    const gn = function () { quickrest({endpoints, root: ''}) }
    const hn = function () { quickrest({endpoints, root: '  '}) }
    expect(fn).to.throw(/required/)
    expect(gn).to.throw(/required/)
    expect(hn).to.throw(/required/)
  })

  let spy
  let api

  beforeEach(() => {
    spy = sinon.spy()
    api = quickrest({root, endpoints, request: spy})
  })

  it('should return a function', () => {
    expect(api).to.be.a('function')
  })

  it('that does not have any REST methods attached', () => {
    expect(api).to.not.have.property('create')
    expect(api).to.not.have.property('get')
    expect(api).to.not.have.property('del')
    expect(api).to.not.have.property('delete')
    expect(api).to.not.have.property('update')
  })

  it('should have top level resources', () => {
    expect(api).to.have.property('users')
    expect(api).to.have.property('posts')
    expect(api).to.have.property('comments')
  })

  it('and inaccessible subresources', () => {
    expect(api).to.not.have.property('users.posts')
    expect(api).to.not.have.property('posts.comments')
  })

  let spy1
  beforeEach(() => {
    spy1 = sinon.spy()
  })

  describe('top-level resources', () => {
    it('urls are prefixed only be root', () => {
      const args = {}
      api.users.create({}, spy1)
      expect(spy).to.have.been.calledWith(`${root}/users`, 'post', args)
    })

    it('have a "get" method that includes resource id', () => {
      api.users(9000).get(spy1)
      expect(spy).to.have.been.calledWith(`${root}/users/9000`, 'get')
    })

    it('as does "del"', () => {
      api.users(9000).del(spy1)
      expect(spy).to.have.been.calledWith(`${root}/users/9000`, 'delete')
    })

    it('and "update"', () => {
      const args = {}
      api.users(9000).update(args, spy1)
      expect(spy).to.have.been.calledWith(`${root}/users/9000`, 'put', args)
    })
  })

  describe('subresources', () => {
    it('include their parent resource\'s fragment in their path', () => {
      const spy2 = sinon.spy()
      const args = {}
      api.users(9000).posts.create(args, spy1)
      expect(spy).to.have.been.calledWith(`${root}/users/9000/posts`, 'post', args)

      api.users(9000).posts(3).comments.create(args, spy2)
      expect(spy).to.have.been.calledWith(`${root}/users/9000/posts/3/comments`, 'post', args)
    })
  })

  describe('config.request', () => {
    beforeEach(() => {
      api = quickrest({root, endpoints})
    })

    it('may return a promise with response data', () => {
      const body = {
        id: 9000,
        email: 'jane.smith@example.com',
      }

      nock(root)
        .get('/users/9000')
        .reply(200, body)

      const promise = api.users(9000).get()

      return PromiseLib.all([
        expect(promise).to.eventually.have.property('model').that.eql(body),
        expect(promise).to.eventually.have.property('status', 200),
      ])
    })

    it('for post', () => {
      const body = {
        title: 'blog post',
        content: 'this is great',
      }

      nock(root)
        .post('/users/9000/posts')
        .reply(200, body)

      const promise = api.users(9000).posts.create(body)

      return PromiseLib.all([
        expect(promise).to.eventually.have.property('model').that.eql(body),
        expect(promise).to.eventually.have.property('status', 200),
      ])
    })

    it('for put', () => {
      const body = {
        title: 'blog post',
        content: 'this is great',
      }

      const resp = Object.assign({id: 4}, body)

      nock(root)
        .put('/users/9000/posts', body)
        .reply(200, resp)

      const promise = api.users(9000).posts.update(body)

      return PromiseLib.all([
        expect(promise).to.eventually.have.property('model').that.eql(resp),
        expect(promise).to.eventually.have.property('status', 200),
      ])
    })

    it('get all', () => {
      const query = {
        page: 2,
        rpp: 50,
      }

      const resp = {
        rpp: query.rpp,
        page: 2,
        items: []
      }

      nock(root)
        .get('/users/9000/posts')
        .query(query)
        .reply(200, resp)

      const promise = api.users(9000).posts.list(query)

      return PromiseLib.all([
        expect(promise).to.eventually.have.property('model').that.eql(resp),
        expect(promise).to.eventually.have.property('status', 200),
      ])
    })

    it('and delete', () => {
      nock(root)
        .delete('/users/9000')
        .reply(204)

      const promise = api.users(9000).del()

      return PromiseLib.all([
        expect(promise).to.eventually.have.property('status', 204),
      ])
    })

    it('may return a reject promise if the request fails', () => {
      nock(root)
        .delete('/users/9001')
        .reply(404)

      const promise = api.users(9001).del()

      return PromiseLib.all([
        expect(promise).to.be.rejected
      ])
    })

    it('invokes a callback with response data', (done) => {
      const body = {
        id: 9000,
        email: 'jane.smith@example.com',
      }

      nock(root)
        .get('/users/9000')
        .reply(200, body)

      api.users(9000).get((err, res) => {
        if (err) return done(err)
        expect(res.model).to.eql(body)
        done()
      })
    })

    it('invokes a callback with error data if the request fails', done => {
      const body = {
        id: 9000,
        email: 'jane.smith@example.com',
      }

      nock(root)
        .get('/users/9000')
        .reply(404, body)

      api.users(9000).get((err, res) => {
        expect(err).to.exist.be.an.instanceOf(Error)
        expect(res.status).to.equal(404)
        done()
      })
    })
  })

  describe('config.versions', () => {
    it('allows you to gracefully evolve an API', () => {
      api = quickrest({endpoints, root, versions: 'v1'})
      expect(api.v1).to.exist
      expect(api.v1().users).to.exist
    })
  })

  describe('config.altMethodNames', () => {
    it('defines new method names to prevent name clashes', () => {
      api = quickrest({
        endpoints,
        root,
        altMethodNames: {
          get: 'fetch',
        }
      })

      expect(api.users.fetch).to.exist.to.be.a('function')
      expect(api.users.create).to.exist.to.be.a('function')
    })
  })

  describe('config.endpoints', () => {
    it('accepts a string or object containing a "resource" property', () => {
      api = quickrest({
        root,
        endpoints: [
          'users',
          {
            resource: 'plays',
          }
        ]
      })

      expect(api.users).to.exist
      expect(api.plays).to.exist
    })

    it('accepts an alt http verb for creating that resource', () => {

    })
  })
})
<|endoftext|>


<commit_before>var robots = require('index');

function MockSite() {
  this.settings = {};
  this.pages = {};
}

MockSite.prototype.get =
MockSite.prototype.set = function(setting, val) {
  if (1 == arguments.length) {
    return this.settings[setting];
  } else {
    this.settings[setting] = val;
    return this;
  }
}

MockSite.prototype.page = function(path, fn) {
  this.pages[path] = new MockPage(path, fn);
}

function MockPage(path, fn) {
  this.path = path;
  this.fn = fn;
  this.data = '';
}

MockPage.prototype.write = function(data) {
  this.data += data;
}

describe('robots plugin', function() {

  it('should export function', function() {
    expect(robots).to.be.a('function');
  });

  describe('when invoked', function() {
    var site = new MockSite();
    site.set('base url', 'http://www.example.com/')

    robots()(site, site.pages);

    it('should add robots.txt page', function() {
      expect(site.pages).to.include.keys('/robots.txt');
    });

    describe('and then rendering robots.txt', function() {
      var p = site.pages['/robots.txt'];

      it('should write robots.txt', function(done) {
        var expected = [
          "User-agent: *",
          "Disallow:",
        ].join("\r\n");
        expected += "\r\n\r\n";

        p.end = function() {
          expect(p.data).to.equal(expected);
          done();
        };

        p.fn(p, function(err) {
          return done(new Error('should not call next'));
        });
      });
    });
  });

  describe('when invoked on a site without base url setting', function() {
    var site = new MockSite();

    it('should throw an error', function() {
      expect(function() {
        robots()(site, site.pages);
      }).to.throw(/requires \"base url\" setting/);
    });
  });

});
<commit_msg>Test case for rendering robots.txt with sitemap.<commit_after>var robots = require('index');

function MockSite() {
  this.settings = {};
  this.pages = {};
}

MockSite.prototype.get =
MockSite.prototype.set = function(setting, val) {
  if (1 == arguments.length) {
    return this.settings[setting];
  } else {
    this.settings[setting] = val;
    return this;
  }
}

MockSite.prototype.page = function(path, fn) {
  this.pages[path] = new MockPage(path, fn);
}

function MockPage(path, fn) {
  this.path = path;
  this.fn = fn;
  this.data = '';
}

MockPage.prototype.write = function(data) {
  this.data += data;
}

describe('robots plugin', function() {

  it('should export function', function() {
    expect(robots).to.be.a('function');
  });

  describe('when invoked', function() {
    var site = new MockSite();
    site.set('base url', 'http://www.example.com/')

    robots()(site, site.pages);

    it('should add robots.txt page', function() {
      expect(site.pages).to.include.keys('/robots.txt');
    });

    describe('and then rendering robots.txt', function() {
      var p = site.pages['/robots.txt'];

      it('should write robots.txt', function(done) {
        var expected = [
          "User-agent: *",
          "Disallow:",
          "",
          ""
        ].join("\r\n");

        p.end = function() {
          expect(p.data).to.equal(expected);
          done();
        };

        p.fn(p, function(err) {
          return done(new Error('should not call next'));
        });
      });
    });
  });

  describe('when invoked on a site with a sitemap', function() {
    var site = new MockSite();
    site.set('base url', 'http://www.example.com/')

    site.page('/sitemap.xml', function(){});
    site.pages['/sitemap.xml'].sitemap = true;

    robots()(site, site.pages);

    it('should add robots.txt page', function() {
      expect(site.pages).to.include.keys('/robots.txt');
    });

    describe('and then rendering robots.txt', function() {
      var p = site.pages['/robots.txt'];

      it('should write robots.txt', function(done) {
        var expected = [
          "User-agent: *",
          "Disallow:",
          "",
          "Sitemap: http://www.example.com/sitemap.xml",
          ""
        ].join("\r\n");

        p.end = function() {
          expect(p.data).to.equal(expected);
          done();
        };

        p.fn(p, function(err) {
          return done(new Error('should not call next'));
        });
      });
    });
  });

  describe('when invoked on a site without base url setting', function() {
    var site = new MockSite();

    it('should throw an error', function() {
      expect(function() {
        robots()(site, site.pages);
      }).to.throw(/requires \"base url\" setting/);
    });
  });

});
<|endoftext|>


<commit_before>var http = require('http');
var https = require('https');
var parseUrl = require('url').parse;
var net = require('net');
var path = require('path');
var StringDecoder = require('string_decoder').StringDecoder;
require('should');
require('should-http');
var fs = require('fs');
var fse = require('fs-extra');
var startWhistle = require('../index');
var socks = require('socksv5');
var util = require('./util.test');
var config = require('./config.test');
var values = util.getValues();
var testList = ['ws.test'].map(function(name) {
  return require('./units/' + name);
});
var defaultRules = fs.readFileSync(path.join(__dirname, 'rules.txt'), {encoding: 'utf8'});
var options = {
  key: fs.readFileSync(path.join(__dirname, 'assets/certs/root.key')),
  cert: fs.readFileSync(path.join(__dirname, 'assets/certs/_root.crt'))
};
var count = 6;

var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ port: config.wsPort });
var WHISTLE_PATH = process.env.WHISTLE_PATH = __dirname;
var PLUGINS_PATH = path.join(WHISTLE_PATH, '.whistle/node_modules');

fse.removeSync(path.join(WHISTLE_PATH, '.whistle'));
fse.copySync(path.join(__dirname, 'plugins'), PLUGINS_PATH);

wss.on('connection', function connection(ws) {
  var req = ws.upgradeReq;
  ws.on('message', function(msg) {
    ws.send(JSON.stringify({
      type: 'server',
      method: req.method,
      headers: req.headers,
      body: msg
    }, null, '\t'));
  });
});

http.createServer(function(req, res) {
  req.on('error', util.noop);
  res.on('error', util.noop);

  var body = '';
  var decoder = new StringDecoder('utf8');
  req.on('data', function(data) {
    body += decoder.write(data);
  });
  req.on('end', function() {
    body += decoder.end();
    res.end(JSON.stringify({
      type: 'server',
      url: req.url,
      method: req.method,
      headers: req.headers,
      body: body
    }, null, '\t'));
  });
}).listen(config.serverPort, startTest);

https.createServer(options, function(req, res) {
  res.end(JSON.stringify({
    headers: req.headers,
    body: 'test'
  }));
}).listen(config.httpsPort, startTest);
values['options.html'] = {
  method: 'options'
};
var proxy = startWhistle({
  port: config.port,
  storage: 'test_',
  certDir: path.join(__dirname, 'assets/certs'),
  debugMode: true,
  localUIHost: 'local.whistle.com',
  rules: {
    Default: defaultRules,
    test: {
      rules: 'test.options.com file://{options.html}',
      enable: true
    },
    abc: '123'
  },
  values: values,
  copy: true
}, startTest);

proxy.on('tunnelRequest', util.noop);
proxy.on('wsRequest', util.noop);
proxy.on('_request', util.noop);
var socksServer = socks.createServer(function(info, accept, deny) {
  var socket;
  if (info.dstPort === 443) {
    if (socket = accept(true)) {
      var client = net.connect({
        host: '127.0.0.1',
        port: 5566
      }, function() {
        socket.pipe(client).pipe(socket);
      });
    }
    return;
  }
  if (info.dstPort === 8081) {
    if (socket = accept(true)) {
      var client = net.connect({
        host: '127.0.0.1',
        port: 8081
      }, function() {
        socket.pipe(client).pipe(socket);
      });
    }
    return;
  }
  if (socket = accept(true)) {
    var body = JSON.stringify({
      port: config.socksPort
    });
    socket.end([
      'HTTP/1.1 200 OK',
      'Connection: close',
      'Content-Type: text/plain;charset=utf8',
      'Content-Length: ' + Buffer.byteLength(body),
      '',
      body
    ].join('\r\n'));
  }
});

var authSocksServer = socks.createServer(function(info, accept, deny) {
  var socket;
  if (info.dstPort === 443) {
    if (socket = accept(true)) {
      var client = net.connect({
        host: '127.0.0.1',
        port: 5566
      }, function() {
        socket.pipe(client).pipe(socket);
      });
    }
    return;
  }
  if (socket = accept(true)) {
    var body = JSON.stringify({
      port: config.authSocksPort
    });
    socket.end([
      'HTTP/1.1 200 OK',
      'Connection: close',
      'Content-Type: text/plain;charset=utf8',
      'Content-Length: ' + Buffer.byteLength(body),
      '',
      body
    ].join('\r\n'));
  }
});

socksServer.useAuth(socks.auth.None());
authSocksServer.useAuth(socks.auth.UserPassword(function(user, password, cb) {
  cb(user == 'test' && password == 'hello1234');
}));

socksServer.listen(config.socksPort, startTest);
authSocksServer.listen(config.authSocksPort, startTest);

/**
 * 不用处理异常
 */
var server = http.createServer(function(req, res) {
  var fullUrl = /^http:/.test(req.url) ? req.url : 'http://' + req.headers.host + req.url;
  var options = parseUrl(fullUrl);
  delete options.hostname;
  options.host = '127.0.0.1';
  options.method = req.method;
  options.headers = req.headers;
  var client = http.request(options, function(_res) {
    _res.pipe(res);
  });
  req.pipe(client);
});

server.on('connect', function(req, socket) {
  var tunnelUrl = 'tunnel://' + (/^[^:\/]+:\d+$/.test(req.url) ? req.url : req.headers.host);
  var options = parseUrl(tunnelUrl);
  var client = net.connect({
    host: '127.0.0.1',
    port: options.port || 443
  }, function() {
    socket.pipe(client).pipe(socket);
    socket.write('HTTP/1.1 200 Connection Established\r\nProxy-Agent: whistle/test\r\n\r\n');
  });
});

server.listen(config.proxyPort, startTest);

function startTest() {
  if (--count > 0) {
    return;
  }

  var done;
  function testAll() {
    if (done) {
      return;
    }
    done = true;
    testList.forEach(function(fn) {
      fn();
    });
  }

  (function getData() {
    util.request('http://local.whistlejs.com/cgi-bin/get-data', function() {
      testAll();
      setTimeout(getData, 5000);
    });
  })();
}

<commit_msg>test: urlParams<commit_after>var http = require('http');
var https = require('https');
var parseUrl = require('url').parse;
var net = require('net');
var path = require('path');
var StringDecoder = require('string_decoder').StringDecoder;
require('should');
require('should-http');
var fs = require('fs');
var fse = require('fs-extra');
var startWhistle = require('../index');
var socks = require('socksv5');
var util = require('./util.test');
var config = require('./config.test');
var values = util.getValues();
var testList = fs.readdirSync(path.join(__dirname, './units')).map(function(name) {
  return require('./units/' + name);
});
var defaultRules = fs.readFileSync(path.join(__dirname, 'rules.txt'), {encoding: 'utf8'});
var options = {
  key: fs.readFileSync(path.join(__dirname, 'assets/certs/root.key')),
  cert: fs.readFileSync(path.join(__dirname, 'assets/certs/_root.crt'))
};
var count = 6;

var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ port: config.wsPort });
var WHISTLE_PATH = process.env.WHISTLE_PATH = __dirname;
var PLUGINS_PATH = path.join(WHISTLE_PATH, '.whistle/node_modules');

fse.removeSync(path.join(WHISTLE_PATH, '.whistle'));
fse.copySync(path.join(__dirname, 'plugins'), PLUGINS_PATH);

wss.on('connection', function connection(ws) {
  var req = ws.upgradeReq;
  ws.on('message', function(msg) {
    ws.send(JSON.stringify({
      type: 'server',
      method: req.method,
      headers: req.headers,
      body: msg
    }, null, '\t'));
  });
});

http.createServer(function(req, res) {
  req.on('error', util.noop);
  res.on('error', util.noop);

  var body = '';
  var decoder = new StringDecoder('utf8');
  req.on('data', function(data) {
    body += decoder.write(data);
  });
  req.on('end', function() {
    body += decoder.end();
    res.end(JSON.stringify({
      type: 'server',
      url: req.url,
      method: req.method,
      headers: req.headers,
      body: body
    }, null, '\t'));
  });
}).listen(config.serverPort, startTest);

https.createServer(options, function(req, res) {
  res.end(JSON.stringify({
    headers: req.headers,
    body: 'test'
  }));
}).listen(config.httpsPort, startTest);
values['options.html'] = {
  method: 'options'
};
var proxy = startWhistle({
  port: config.port,
  storage: 'test_',
  certDir: path.join(__dirname, 'assets/certs'),
  debugMode: true,
  localUIHost: 'local.whistle.com',
  rules: {
    Default: defaultRules,
    test: {
      rules: 'test.options.com file://{options.html}',
      enable: true
    },
    abc: '123'
  },
  values: values,
  copy: true
}, startTest);

proxy.on('tunnelRequest', util.noop);
proxy.on('wsRequest', util.noop);
proxy.on('_request', util.noop);
var socksServer = socks.createServer(function(info, accept, deny) {
  var socket;
  if (info.dstPort === 443) {
    if (socket = accept(true)) {
      var client = net.connect({
        host: '127.0.0.1',
        port: 5566
      }, function() {
        socket.pipe(client).pipe(socket);
      });
    }
    return;
  }
  if (info.dstPort === 8081) {
    if (socket = accept(true)) {
      var client = net.connect({
        host: '127.0.0.1',
        port: 8081
      }, function() {
        socket.pipe(client).pipe(socket);
      });
    }
    return;
  }
  if (socket = accept(true)) {
    var body = JSON.stringify({
      port: config.socksPort
    });
    socket.end([
      'HTTP/1.1 200 OK',
      'Connection: close',
      'Content-Type: text/plain;charset=utf8',
      'Content-Length: ' + Buffer.byteLength(body),
      '',
      body
    ].join('\r\n'));
  }
});

var authSocksServer = socks.createServer(function(info, accept, deny) {
  var socket;
  if (info.dstPort === 443) {
    if (socket = accept(true)) {
      var client = net.connect({
        host: '127.0.0.1',
        port: 5566
      }, function() {
        socket.pipe(client).pipe(socket);
      });
    }
    return;
  }
  if (socket = accept(true)) {
    var body = JSON.stringify({
      port: config.authSocksPort
    });
    socket.end([
      'HTTP/1.1 200 OK',
      'Connection: close',
      'Content-Type: text/plain;charset=utf8',
      'Content-Length: ' + Buffer.byteLength(body),
      '',
      body
    ].join('\r\n'));
  }
});

socksServer.useAuth(socks.auth.None());
authSocksServer.useAuth(socks.auth.UserPassword(function(user, password, cb) {
  cb(user == 'test' && password == 'hello1234');
}));

socksServer.listen(config.socksPort, startTest);
authSocksServer.listen(config.authSocksPort, startTest);

/**
 * 不用处理异常
 */
var server = http.createServer(function(req, res) {
  var fullUrl = /^http:/.test(req.url) ? req.url : 'http://' + req.headers.host + req.url;
  var options = parseUrl(fullUrl);
  delete options.hostname;
  options.host = '127.0.0.1';
  options.method = req.method;
  options.headers = req.headers;
  var client = http.request(options, function(_res) {
    _res.pipe(res);
  });
  req.pipe(client);
});

server.on('connect', function(req, socket) {
  var tunnelUrl = 'tunnel://' + (/^[^:\/]+:\d+$/.test(req.url) ? req.url : req.headers.host);
  var options = parseUrl(tunnelUrl);
  var client = net.connect({
    host: '127.0.0.1',
    port: options.port || 443
  }, function() {
    socket.pipe(client).pipe(socket);
    socket.write('HTTP/1.1 200 Connection Established\r\nProxy-Agent: whistle/test\r\n\r\n');
  });
});

server.listen(config.proxyPort, startTest);

function startTest() {
  if (--count > 0) {
    return;
  }

  var done;
  function testAll() {
    if (done) {
      return;
    }
    done = true;
    testList.forEach(function(fn) {
      fn();
    });
  }

  (function getData() {
    util.request('http://local.whistlejs.com/cgi-bin/get-data', function() {
      testAll();
      setTimeout(getData, 5000);
    });
  })();
}

<|endoftext|>


<commit_before>require('./koa.test');
require('./express.test');

var util = require('./util.test');
var proxy = require('../lib');
before(function(done) {
  proxy.ready().then(function(port) {
      Promise.all([
        util.startHttpServer(),
        util.startProxyServer(),
        util.startSocksServer(),
        util.startSocketServer(),
      ]).then(function() {
        done();
      });
  });
});
require('./units/connect.test');
require('./units/request.test');
<commit_msg>test: request<commit_after>require('./koa.test');
require('./express.test');

var util = require('./util.test');
var proxy = require('../lib');
before(function(done) {
  proxy.ready().then(function(port) {
      Promise.all([
        util.startHttpServer(),
        util.startProxyServer(),
        util.startSocksServer(),
        util.startSocketServer(),
      ]).then(function() {
        done();
      });
  });
});
require('./units/connect.test');
// require('./units/request.test');
<|endoftext|>


<commit_before>'use strict';

var Analytics = require('@segment/analytics.js-core').constructor;
// var each = require('component-each');
var integration = require('@segment/analytics.js-integration');
var sandbox = require('@segment/clear-env');
var tester = require('@segment/analytics.js-integration-tester');
var KilometerIntegration = require('../lib/');

describe('Kilometer.io', function() {
  var kilometerIntegration;
  var analytics;
  var options = {
    app_id: 'fakeId',
    endPoint: 'events.stage.kilometer.io',
    webUrl: 'app.stage.kilometer.io/events/save/'
  };

  beforeEach(function() {
    console.log('Entered test Kilometer.io > beforeEach()');
    analytics = new Analytics();
    kilometerIntegration = new KilometerIntegration(options);
    analytics.use(KilometerIntegration);
    analytics.use(tester);
    analytics.add(kilometerIntegration);
  });

  afterEach(function() {
    console.log('Entered test Kilometer.io > afterEach()');
    analytics.restore();
    analytics.reset();
    kilometerIntegration.reset();
    sandbox();
  });

  it('should have the right settings', function() {
    console.log('Entered test Kilometer.io > it(should have the right settings)');
    analytics.compare(KilometerIntegration, integration('Kilometer.io')
        .global('kilometerIntegration')
        .option('app_id', '')
        .tag('<script src="//static.kilometer.io/staging/js/events-api-client2.js.js">'));
  });

  describe('before loading', function() {
    beforeEach(function() {
      console.log('Entered test Kilometer.io > before loading > beforeEach()');
      analytics.stub(kilometerIntegration, 'load');
    });

    afterEach(function() {
      console.log('Entered test Kilometer.io > before loading > afterEach()');
      if (typeof window.Kilometer !== 'undefined' || window.Kilometer !== null) {
        window.Kilometer = null;
      }
    });

    describe('#initialize', function() {
      it('should create window.Kilometer', function() {
        console.log('Entered test Kilometer.io > before loading > #initialize > it(should create window.Kilometer)');
        analytics.assert(!window.Kilometer);
        analytics.initialize();
        analytics.assert(window.Kilometer);
      });

      /*
      it('should stub window.kilometerIntegration with the right methods', function() {
        console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.kilometerIntegration with the right methods)');
        // transmitEvent identify addUser setUserProperties increaseUserProperty decreaseUserProperty
        var methods = ['track', 'initialize', 'identify', 'loaded'];
        analytics.assert(!window.kilometerIntegration);
        analytics.initialize();
        each(methods, function(method) {
          analytics.assert(window.kilometerIntegration[method]);
        });
      });
      */

      it('should stub window.Kilometer with the right methods', function() {
        console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.Kilometer with the right methods)');
        // transmitEvent identify addUser setUserProperties increaseUserProperty decreaseUserProperty
        var methods = ['transmitEvent', 'identify', 'addUser', 'setUserProperties', 'increaseUserProperty', 'decreaseUserProperty'];
        analytics.assert(!window.Kilometer);
        analytics.initialize();
        analytics.assert(window.Kilometer);

        /*
        // Print Kilometer object's fields
        for (var key in window.Kilometer) {
          if (key) {
            console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.Kilometer with the right methods) : Kilometer.' + key + ' = ' + window.Kilometer[key]);
          }
        }
        */

        // Print Kilometer object's fields
        /*
        for (var key in analytics) {
          // var keys = ['Integrations', 'options', '_user', 'spy', 'stub', 'restore', 'spies', 'called', 'load', 'loaded', 'integration', '']

          if (key) {
            console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.Kilometer with the right methods) : analytics.' + key + ' = ' + analytics[key]);
          }
        }
        */

        /*
        var integration = analytics.integration('Kilometer.io');
        console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.Kilometer with the right methods) : analytics.integration[Kilometer.io] = ' + integration);
        for (var m in integration) {
          if (m) {
            console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.Kilometer with the right methods) : analytics.integration[Kilometer.io].' + m + ' = ' + integration[m]);
          }
        }
        */

        /*
        var Integrations = analytics.Integrations;
        for (var _i in Integrations) {
          if (_i) {
            console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.Kilometer with the right methods) : analytics.Integrations.' + _i + ' = ' + Integrations[_i]);
          }
        }
        */

        methods.forEach(function(method) {
          analytics.assert(window.Kilometer[method]);
        });
      });

      it('should set window.Kilometer.app_id', function() {
        console.log('Entered test Kilometer.io > before loading > #initialize > it(should set window.Kilometer.app_id)');
        analytics.assert(!window.Kilometer);
        analytics.initialize();
        analytics.assert(window.Kilometer.app_id === options.app_id);
      });

      it('should call #load', function() {
        console.log('Entered test Kilometer.io > before loading > #initialize > it(should call #load)');
        analytics.initialize();
        analytics.called(kilometerIntegration.load);
      });
    });
  });

  describe('loading', function() {
    it('should load', function(done) {
      console.log('Entered test Kilometer.io > loading > it(should load)');
      // console.log('Entered test Kilometer.io > loading > it(should load) : analytics.load = ' + analytics['load']);
      // console.log('Entered test Kilometer.io > loading > it(should load) : analytics.load = ' + analytics['load']);
      analytics.load(kilometerIntegration, done);
    });
  });

  describe('after loading', function() {
    beforeEach(function(done) {
      sandbox();
      analytics.once('ready', done);
      analytics.initialize();
      analytics.page();
    });

    afterEach(function() {
      console.log('Entered test Kilometer.io > after loading > afterEach()');
      //  if (typeof window.Kilometer !== 'undefined' || window.Kilometer !== null) {
      //  window.Kilometer = null;
      // }
      // sandbox();
    });

    describe('#identify', function() {
      beforeEach(function() {
        sandbox();
        analytics.stub(window.Kilometer, 'identify');
        analytics.stub(window.Kilometer, 'setUserProperties');
      });

      // afterEach(function() {
      //  sandbox();
      //  analytics = null;
      //  window.Kilometer = null;
      // });

      it('if no user id is specified - do not do anything', function() {
        analytics.identify({ trait: true, number: 1 });
        analytics.didNotCall(window.Kilometer.identify);
        analytics.didNotCall(window.Kilometer.setUserProperties);
      });

      it('should send traits', function() {
        sandbox();
        analytics.identify('vasya2', { trait: true, number: 1 });
        analytics.called(window.Kilometer.setUserProperties, { trait: true, number: 1 });
      });

      it('should send id as handle', function() {
        analytics.identify('id');
        analytics.called(window.Kilometer.identify, 'id');
      });

      it('should send id as handle and traits', function() {
        sandbox();
        analytics.identify('id', { trait: 'trait' });
        analytics.called(window.Kilometer.identify, 'id');
        analytics.called(window.Kilometer.setUserProperties, { trait: 'trait' });
      });

      it('should flatten nested objects and arrays', function() {
        analytics.identify('id', {
          email: 'teemo@teemo.com',
          property: 3,
          foo: {
            bar: {
              hello: 'teemo'
            },
            cheese: ['1', 2, 'cheers'],
            products: [
              { A: 'Jello' },
              { B: 'Peanut' }
            ]
          }
        });
        analytics.called(window.Kilometer.identify, 'id');
        analytics.called(window.Kilometer.setUserProperties, {
          email: 'teemo@teemo.com',
          property: 3,
          'foo.bar.hello': 'teemo',
          'foo.cheese': '[\"1\",2,\"cheers\"]',
          'foo.products': '[{\"A\":\"Jello\"},{\"B\":\"Peanut\"}]'
        });
      });

      it('should send date traits as ISOStrings', function() {
        var date = new Date('2016');
        analytics.identify('id', { date: date });
        analytics.called(window.Kilometer.identify, 'id');
        analytics.called(window.Kilometer.setUserProperties, { date: '2016-01-01T00:00:00.000Z' });
      });
    });

    describe('#track', function() {
      beforeEach(function() {
        analytics.stub(window.Kilometer, 'transmitEvent');
      });

      it('should send an event', function() {
        analytics.track('event');
        analytics.called(window.Kilometer.transmitEvent, 'event');
      });

      it('should send an event and properties', function() {
        analytics.track('event', { property: true });
        analytics.called(window.Kilometer.transmitEvent, 'event', { property: true });
      });

      it('should flatten nested objects and arrays', function() {
        analytics.track('event', {
          property: 3,
          foo: {
            bar: {
              hello: 'teemo'
            },
            cheese: ['1', 2, 'cheers'],
            products: [
              { A: 'Jello' },
              { B: 'Peanut' }
            ]
          }
        });
        analytics.called(window.Kilometer.transmitEvent, 'event', {
          property: 3,
          'foo.bar.hello': 'teemo',
          'foo.cheese': '[\"1\",2,\"cheers\"]',
          'foo.products': '[{\"A\":\"Jello\"},{\"B\":\"Peanut\"}]'
        });
      });
    });
  });
});<commit_msg>remove redundant test<commit_after>'use strict';

var Analytics = require('@segment/analytics.js-core').constructor;
// var each = require('component-each');
var integration = require('@segment/analytics.js-integration');
var sandbox = require('@segment/clear-env');
var tester = require('@segment/analytics.js-integration-tester');
var KilometerIntegration = require('../lib/');

describe('Kilometer.io', function() {
  var kilometerIntegration;
  var analytics;
  var options = {
    app_id: 'fakeId',
    endPoint: 'events.stage.kilometer.io',
    webUrl: 'app.stage.kilometer.io/events/save/'
  };

  beforeEach(function() {
    console.log('Entered test Kilometer.io > beforeEach()');
    analytics = new Analytics();
    kilometerIntegration = new KilometerIntegration(options);
    analytics.use(KilometerIntegration);
    analytics.use(tester);
    analytics.add(kilometerIntegration);
  });

  afterEach(function() {
    console.log('Entered test Kilometer.io > afterEach()');
    analytics.restore();
    analytics.reset();
    kilometerIntegration.reset();
    sandbox();
  });

  it('should have the right settings', function() {
    console.log('Entered test Kilometer.io > it(should have the right settings)');
    analytics.compare(KilometerIntegration, integration('Kilometer.io')
        .global('kilometerIntegration')
        .option('app_id', '')
        .tag('<script src="//static.kilometer.io/staging/js/events-api-client2.js.js">'));
  });

  describe('before loading', function() {
    beforeEach(function() {
      console.log('Entered test Kilometer.io > before loading > beforeEach()');
      analytics.stub(kilometerIntegration, 'load');
    });

    afterEach(function() {
      console.log('Entered test Kilometer.io > before loading > afterEach()');
      if (typeof window.Kilometer !== 'undefined' || window.Kilometer !== null) {
        window.Kilometer = null;
      }
    });

    describe('#initialize', function() {
      it('should create window.Kilometer', function() {
        console.log('Entered test Kilometer.io > before loading > #initialize > it(should create window.Kilometer)');
        analytics.assert(!window.Kilometer);
        analytics.initialize();
        analytics.assert(window.Kilometer);
      });

      it('should stub window.Kilometer with the right methods', function() {
        console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.Kilometer with the right methods)');
        // transmitEvent identify addUser setUserProperties increaseUserProperty decreaseUserProperty
        var methods = ['transmitEvent', 'identify', 'addUser', 'setUserProperties', 'increaseUserProperty', 'decreaseUserProperty'];
        analytics.assert(!window.Kilometer);
        analytics.initialize();
        analytics.assert(window.Kilometer);

        /*
        // Print Kilometer object's fields
        for (var key in window.Kilometer) {
          if (key) {
            console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.Kilometer with the right methods) : Kilometer.' + key + ' = ' + window.Kilometer[key]);
          }
        }
        */

        // Print Kilometer object's fields
        /*
        for (var key in analytics) {
          // var keys = ['Integrations', 'options', '_user', 'spy', 'stub', 'restore', 'spies', 'called', 'load', 'loaded', 'integration', '']

          if (key) {
            console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.Kilometer with the right methods) : analytics.' + key + ' = ' + analytics[key]);
          }
        }
        */

        /*
        var integration = analytics.integration('Kilometer.io');
        console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.Kilometer with the right methods) : analytics.integration[Kilometer.io] = ' + integration);
        for (var m in integration) {
          if (m) {
            console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.Kilometer with the right methods) : analytics.integration[Kilometer.io].' + m + ' = ' + integration[m]);
          }
        }
        */

        /*
        var Integrations = analytics.Integrations;
        for (var _i in Integrations) {
          if (_i) {
            console.log('Entered test Kilometer.io > before loading > #initialize > it(should stub window.Kilometer with the right methods) : analytics.Integrations.' + _i + ' = ' + Integrations[_i]);
          }
        }
        */

        methods.forEach(function(method) {
          analytics.assert(window.Kilometer[method]);
        });
      });

      it('should set window.Kilometer.app_id', function() {
        console.log('Entered test Kilometer.io > before loading > #initialize > it(should set window.Kilometer.app_id)');
        analytics.assert(!window.Kilometer);
        analytics.initialize();
        analytics.assert(window.Kilometer.app_id === options.app_id);
      });

      it('should call #load', function() {
        console.log('Entered test Kilometer.io > before loading > #initialize > it(should call #load)');
        analytics.initialize();
        analytics.called(kilometerIntegration.load);
      });
    });
  });

  describe('loading', function() {
    it('should load', function(done) {
      console.log('Entered test Kilometer.io > loading > it(should load)');
      // console.log('Entered test Kilometer.io > loading > it(should load) : analytics.load = ' + analytics['load']);
      // console.log('Entered test Kilometer.io > loading > it(should load) : analytics.load = ' + analytics['load']);
      analytics.load(kilometerIntegration, done);
    });
  });

  describe('after loading', function() {
    beforeEach(function(done) {
      sandbox();
      analytics.once('ready', done);
      analytics.initialize();
      analytics.page();
    });

    afterEach(function() {
      console.log('Entered test Kilometer.io > after loading > afterEach()');
      //  if (typeof window.Kilometer !== 'undefined' || window.Kilometer !== null) {
      //  window.Kilometer = null;
      // }
      // sandbox();
    });

    describe('#identify', function() {
      beforeEach(function() {
        sandbox();
        analytics.stub(window.Kilometer, 'identify');
        analytics.stub(window.Kilometer, 'setUserProperties');
      });

      // afterEach(function() {
      //  sandbox();
      //  analytics = null;
      //  window.Kilometer = null;
      // });

      it('if no user id is specified - do not do anything', function() {
        analytics.identify({ trait: true, number: 1 });
        analytics.didNotCall(window.Kilometer.identify);
        analytics.didNotCall(window.Kilometer.setUserProperties);
      });

      it('should send traits', function() {
        sandbox();
        analytics.identify('vasya2', { trait: true, number: 1 });
        analytics.called(window.Kilometer.setUserProperties, { trait: true, number: 1 });
      });

      it('should send id as handle', function() {
        analytics.identify('id');
        analytics.called(window.Kilometer.identify, 'id');
      });

      it('should send id as handle and traits', function() {
        sandbox();
        analytics.identify('id', { trait: 'trait' });
        analytics.called(window.Kilometer.identify, 'id');
        analytics.called(window.Kilometer.setUserProperties, { trait: 'trait' });
      });

      it('should flatten nested objects and arrays', function() {
        analytics.identify('id', {
          email: 'teemo@teemo.com',
          property: 3,
          foo: {
            bar: {
              hello: 'teemo'
            },
            cheese: ['1', 2, 'cheers'],
            products: [
              { A: 'Jello' },
              { B: 'Peanut' }
            ]
          }
        });
        analytics.called(window.Kilometer.identify, 'id');
        analytics.called(window.Kilometer.setUserProperties, {
          email: 'teemo@teemo.com',
          property: 3,
          'foo.bar.hello': 'teemo',
          'foo.cheese': '[\"1\",2,\"cheers\"]',
          'foo.products': '[{\"A\":\"Jello\"},{\"B\":\"Peanut\"}]'
        });
      });

      it('should send date traits as ISOStrings', function() {
        var date = new Date('2016');
        analytics.identify('id', { date: date });
        analytics.called(window.Kilometer.identify, 'id');
        analytics.called(window.Kilometer.setUserProperties, { date: '2016-01-01T00:00:00.000Z' });
      });
    });

    describe('#track', function() {
      beforeEach(function() {
        analytics.stub(window.Kilometer, 'transmitEvent');
      });

      it('should send an event', function() {
        analytics.track('event');
        analytics.called(window.Kilometer.transmitEvent, 'event');
      });

      it('should send an event and properties', function() {
        analytics.track('event', { property: true });
        analytics.called(window.Kilometer.transmitEvent, 'event', { property: true });
      });

      it('should flatten nested objects and arrays', function() {
        analytics.track('event', {
          property: 3,
          foo: {
            bar: {
              hello: 'teemo'
            },
            cheese: ['1', 2, 'cheers'],
            products: [
              { A: 'Jello' },
              { B: 'Peanut' }
            ]
          }
        });
        analytics.called(window.Kilometer.transmitEvent, 'event', {
          property: 3,
          'foo.bar.hello': 'teemo',
          'foo.cheese': '[\"1\",2,\"cheers\"]',
          'foo.products': '[{\"A\":\"Jello\"},{\"B\":\"Peanut\"}]'
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>const React = require('react');
const parse = require('..');
const { html, svg } = require('./data');
const { render } = require('./helpers');

describe('module', () => {
  it('exports default', () => {
    expect(parse.default).toBe(parse);
  });

  it('exports domToReact', () => {
    expect(parse.domToReact).toBe(require('../lib/dom-to-react'));
  });

  it('exports htmlToDOM', () => {
    expect(parse.htmlToDOM).toBe(require('html-dom-parser'));
  });

  it('exports attributesToProps', () => {
    expect(parse.attributesToProps).toBe(require('../lib/attributes-to-props'));
  });
});

describe('HTMLReactParser', () => {
  it.each([undefined, null, {}, [], true, false, 0, 1, () => {}, new Date()])(
    'throws error for value: %p',
    value => {
      expect(() => {
        parse(value);
      }).toThrow(TypeError);
    }
  );

  it('parses "" to []', () => {
    expect(parse('')).toEqual([]);
  });

  it("returns string if it's not HTML", () => {
    const string = 'text';
    expect(parse(string)).toBe(string);
  });

  it('parses single HTML element', () => {
    expect(parse(html.single)).toMatchSnapshot();
  });

  it('parses single HTML element with comment', () => {
    // comment should be ignored
    expect(parse(html.single + html.comment)).toMatchSnapshot();
  });

  it('parses multiple HTML elements', () => {
    expect(parse(html.multiple)).toMatchSnapshot();
  });

  it('parses complex HTML with doctype', () => {
    expect(parse(html.doctype + html.complex)).toMatchSnapshot();
  });

  it('parses empty ')).toMatchSnapshot();
  });

  it('parses empty ')).toMatchSnapshot();
  });

  it('parses form', () => {
    expect(parse(html.form)).toMatchSnapshot();
  });

  it('parses SVG', () => {
    expect(parse(svg.complex)).toMatchSnapshot();
  });

  it('decodes HTML entities', () => {
    const encodedEntities = 'asdf & ÿ ü '';
    const decodedEntities = "asdf & ÿ ü '";
    const reactElement = parse('' + encodedEntities + '');
    expect(reactElement.props.children).toBe(decodedEntities);
  });

  it('escapes tags inside of <title>', () => {
    expect(parse(html.title)).toMatchSnapshot();
  });
});

describe('replace option', () => {
  it('replaces the element if a valid React element is returned', () => {
    const options = {
      replace: node => {
        if (node.name === 'title') {
          return React.createElement('title', {}, 'Replaced Title');
        }
      }
    };
    expect(parse(html.complex, options)).toMatchSnapshot();
  });

  it('does not replace the element if an invalid React element is returned', () => {
    const options = {
      replace: node => {
        if (node.attribs && node.attribs.id === 'header') {
          return {
            type: 'h1',
            props: { children: 'Heading' }
          };
        }
      }
    };
    expect(parse(html.complex, options)).toMatchSnapshot();
  });
});

describe('library option', () => {
  const Preact = require('preact');

  it('converts with Preact instead of React', () => {
    const parsedElement = parse(html.single, { library: Preact });
    const preactElement = Preact.createElement('p', {}, 'foo');
    expect(React.isValidElement(parsedElement)).toBe(false);
    expect(Preact.isValidElement(parsedElement)).toBe(true);
    // remove `__v` key since it's causing test equality to fail
    delete parsedElement.__v;
    delete preactElement.__v;
    expect(parsedElement).toEqual(preactElement);
  });
});

describe('htmlparser2 option', () => {
  it('parses XHTML with xmlMode enabled', () => {
    // using self-closing syntax (`/>`) for non-void elements is invalid
    // which causes elements to nest instead of being rendered correctly
    // enabling htmlparser2 option xmlMode resolves this issue
    const options = { htmlparser2: { xmlMode: true } };
    expect(parse('

', options)).toMatchSnapshot();
  });
});

describe('trim option', () => {
  it('preserves whitespace text nodes when disabled if valid in parent (default)', () => {
    const html = `

\n	\t
\r

`;
    const reactElement = parse(html);
    expect(render(reactElement)).toBe(
      '

\n

'
    );
  });

  it('removes whitespace text nodes when enabled', () => {
    const html = `

 text 	 	\t
\r
\n
`;
    const options = { trim: true };
    const reactElement = parse(html, options);
    expect(render(reactElement)).toBe(
      '

 text

'
    );
  });
});

describe('invalid styles', () => {
  it('copes with invalid styles', () => {
    const html = '
X
';
    const options = {};
    const reactElement = parse(html, options);
    expect(render(reactElement)).toBe('
X
');
  });
});
<commit_msg>test: added snapshot test<commit_after>const React = require('react');
const parse = require('..');
const { html, svg } = require('./data');
const { render } = require('./helpers');

describe('module', () => {
  it('exports default', () => {
    expect(parse.default).toBe(parse);
  });

  it('exports domToReact', () => {
    expect(parse.domToReact).toBe(require('../lib/dom-to-react'));
  });

  it('exports htmlToDOM', () => {
    expect(parse.htmlToDOM).toBe(require('html-dom-parser'));
  });

  it('exports attributesToProps', () => {
    expect(parse.attributesToProps).toBe(require('../lib/attributes-to-props'));
  });
});

describe('HTMLReactParser', () => {
  it.each([undefined, null, {}, [], true, false, 0, 1, () => {}, new Date()])(
    'throws error for value: %p',
    value => {
      expect(() => {
        parse(value);
      }).toThrow(TypeError);
    }
  );

  it('parses "" to []', () => {
    expect(parse('')).toEqual([]);
  });

  it("returns string if it's not HTML", () => {
    const string = 'text';
    expect(parse(string)).toBe(string);
  });

  it('parses single HTML element', () => {
    expect(parse(html.single)).toMatchSnapshot();
  });

  it('parses single HTML element with comment', () => {
    // comment should be ignored
    expect(parse(html.single + html.comment)).toMatchSnapshot();
  });

  it('parses multiple HTML elements', () => {
    expect(parse(html.multiple)).toMatchSnapshot();
  });

  it('parses complex HTML with doctype', () => {
    expect(parse(html.doctype + html.complex)).toMatchSnapshot();
  });

  it('parses empty ')).toMatchSnapshot();
  });

  it('parses empty ')).toMatchSnapshot();
  });

  it('parses form', () => {
    expect(parse(html.form)).toMatchSnapshot();
  });

  it('parses SVG', () => {
    expect(parse(svg.complex)).toMatchSnapshot();
  });

  it('decodes HTML entities', () => {
    const encodedEntities = 'asdf & ÿ ü '';
    const decodedEntities = "asdf & ÿ ü '";
    const reactElement = parse('' + encodedEntities + '');
    expect(reactElement.props.children).toBe(decodedEntities);
  });

  it('escapes tags inside of <title>', () => {
    expect(parse(html.title)).toMatchSnapshot();
  });
});

describe('replace option', () => {
  it('replaces the element if a valid React element is returned', () => {
    const options = {
      replace: node => {
        if (node.name === 'title') {
          return React.createElement('title', {}, 'Replaced Title');
        }
      }
    };
    expect(parse(html.complex, options)).toMatchSnapshot();
  });

  it('does not replace the element if an invalid React element is returned', () => {
    const options = {
      replace: node => {
        if (node.attribs && node.attribs.id === 'header') {
          return {
            type: 'h1',
            props: { children: 'Heading' }
          };
        }
      }
    };
    expect(parse(html.complex, options)).toMatchSnapshot();
  });
});

describe('library option', () => {
  const Preact = require('preact');

  it('converts with Preact instead of React', () => {
    const parsedElement = parse(html.single, { library: Preact });
    const preactElement = Preact.createElement('p', {}, 'foo');
    expect(React.isValidElement(parsedElement)).toBe(false);
    expect(Preact.isValidElement(parsedElement)).toBe(true);
    // remove `__v` key since it's causing test equality to fail
    delete parsedElement.__v;
    delete preactElement.__v;
    expect(parsedElement).toEqual(preactElement);
  });
});

describe('htmlparser2 option', () => {
  it('parses XHTML with xmlMode enabled', () => {
    // using self-closing syntax (`/>`) for non-void elements is invalid
    // which causes elements to nest instead of being rendered correctly
    // enabling htmlparser2 option xmlMode resolves this issue
    const options = { htmlparser2: { xmlMode: true } };
    expect(parse('

', options)).toMatchSnapshot();
  });
});

describe('trim option', () => {
  it('preserves whitespace text nodes when disabled if valid in parent (default)', () => {
    const html = `

\n	\t
\r

`;
    const reactElement = parse(html);
    expect(render(reactElement)).toBe(
      '

\n

'
    );
    expect(reactElement).toMatchInlineSnapshot(`

    `);
  });

  it('removes whitespace text nodes when enabled', () => {
    const html = `

 text 	 	\t
\r
\n
`;
    const options = { trim: true };
    const reactElement = parse(html, options);
    expect(render(reactElement)).toBe(
      '

 text

'
    );
  });
});

describe('invalid styles', () => {
  it('copes with invalid styles', () => {
    const html = '
X
';
    const options = {};
    const reactElement = parse(html, options);
    expect(render(reactElement)).toBe('
X
');
  });
});
<|endoftext|>


<commit_before>var path = require('path');
var fs = require('fs');
var expect = require('chai').expect;
var webpack = require('webpack');

var entryFilePath = path.join(__dirname, 'source/entry.js');
var outputDirPath = path.join(__dirname, 'build');
var outputFileName = 'build.js';
var outputFilePath = path.join(outputDirPath, outputFileName);

describe('Webpack replace loader ...', function () {
  it('should replace with string search', function (done) {
    webpack(
      {
        entry: entryFilePath,
        output: {
          path: outputDirPath,
          filename: outputFileName
        },
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: '__this',
              query: {
                search: 'var value',
                replace: 'var a'
              }
            }
          ]
        }
      },
      function (error, stats) {
        expect(error).to.equal(null);

        fs.readFile(outputFilePath, 'utf8', function (error, contents) {
          expect(error).to.equal(null);
          expect(contents).to.be.a('string');
          expect(contents.indexOf('var value')).to.equal(-1);
          expect(contents.indexOf('var a')).to.not.equal(-1);
          done();
        });
      }
    );
  });

  it('should replace with pattern search', function (done) {
    webpack(
      {
        entry: entryFilePath,
        output: {
          path: outputDirPath,
          filename: outputFileName
        },
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: '__this',
              query: {
                search: 'var VALUE = \'\.*\'',
                replace: 'var a = \'\'',
                flags: 'i'
              }
            }
          ]
        }
      },
      function (error, stats) {
        expect(error).to.equal(null);

        fs.readFile(outputFilePath, 'utf8', function (error, contents) {
          expect(error).to.equal(null);
          expect(contents).to.be.a('string');
          expect(contents.indexOf('var value')).to.equal(-1);
          expect(contents.indexOf('var a = \'\'')).to.not.equal(-1);
          done();
        });
      }
    );
  });

  it('should replace scoped', function (done) {
    webpack(
      {
        entry: entryFilePath,
        output: {
          path: outputDirPath,
          filename: outputFileName
        },
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: '__this',
              query: {
                search: 'var value',
                replace: 'var a'
              }
            },
            {
              test: /bar\.js$/,
              loader: '__this',
              query: {
                search: 'var value',
                replace: 'var bar'
              }
            }
          ]
        }
      },
      function (error, stats) {
        expect(error).to.equal(null);

        fs.readFile(outputFilePath, 'utf8', function (error, contents) {
          expect(error).to.equal(null);
          expect(contents).to.be.a('string');
          expect(contents.indexOf('var value')).to.equal(-1);
          expect(contents.indexOf('var a')).to.not.equal(-1);
          expect(contents.indexOf('var bar')).to.not.equal(-1);
          done();
        });
      }
    );
  });

  it('should replace using string query', function (done) {
    webpack(
      {
        entry: entryFilePath,
        output: {
          path: outputDirPath,
          filename: outputFileName
        },
        module: {
          loaders: [
            {
              test: /\.js$/,
              loaders: [
                '__this?search=var value&replace=var a',
                '__this?search=module.exports = value&replace=module.exports = a'
              ]
            }
          ]
        }
      },
      function (error, stats) {
        expect(error).to.equal(null);

        fs.readFile(outputFilePath, 'utf8', function (error, contents) {
          expect(error).to.equal(null);
          expect(contents).to.be.a('string');
          expect(contents.indexOf('var value')).to.equal(-1);
          expect(contents.indexOf('var a')).to.not.equal(-1);
          expect(contents.indexOf('module.exports = value')).to.equal(-1);
          expect(contents.indexOf('module.exports = a')).to.not.equal(-1);
          done();
        });
      }
    );
  });
});
<commit_msg>Fix tests<commit_after>var path = require('path');
var fs = require('fs');
var expect = require('chai').expect;
var webpack = require('webpack');

var entryFilePath = path.join(__dirname, 'source/entry.js');
var outputDirPath = path.join(__dirname, 'build');
var outputFileName = 'build.js';
var outputFilePath = path.join(outputDirPath, outputFileName);

describe('Webpack replace loader ...', function () {
  it('should replace with string search', function (done) {
    webpack(
      {
        entry: entryFilePath,
        output: {
          path: outputDirPath,
          filename: outputFileName
        },
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: '__this',
              query: {
                replace: [{
                  from: 'var value',
                  to: 'var a'
                }]
              }
            }
          ]
        }
      },
      function (error, stats) {
        expect(error).to.equal(null);

        fs.readFile(outputFilePath, 'utf8', function (error, contents) {
          expect(error).to.equal(null);
          expect(contents).to.be.a('string');
          expect(contents.indexOf('var value')).to.equal(-1);
          expect(contents.indexOf('var a')).to.not.equal(-1);
          done();
        });
      }
    );
  });

  it('should replace scoped', function (done) {
    webpack(
      {
        entry: entryFilePath,
        output: {
          path: outputDirPath,
          filename: outputFileName
        },
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: '__this',
              query: {
                replace: [{
                  from: 'var value',
                  to: 'var a'
                }]
              }
            },
            {
              test: /bar\.js$/,
              loader: '__this',
              query: {
                replace: [{
                  from: 'var value',
                  to: 'var a'
                }]
              }
            }
          ]
        }
      },
      function (error, stats) {
        expect(error).to.equal(null);

        fs.readFile(outputFilePath, 'utf8', function (error, contents) {
          expect(error).to.equal(null);
          expect(contents).to.be.a('string');
          expect(contents.indexOf('var value')).to.equal(-1);
          expect(contents.indexOf('var a')).to.not.equal(-1);
          expect(contents.indexOf('var bar')).to.not.equal(-1);
          done();
        });
      }
    );
  });

  it('should replace using string query', function (done) {
    webpack(
      {
        entry: entryFilePath,
        output: {
          path: outputDirPath,
          filename: outputFileName
        },
        module: {
          loaders: [
            {
              test: /\.js$/,
              loaders: [
                '__this?search=var value&replace=var a',
                '__this?search=module.exports = value&replace=module.exports = a'
              ]
            }
          ]
        }
      },
      function (error, stats) {
        expect(error).to.equal(null);

        fs.readFile(outputFilePath, 'utf8', function (error, contents) {
          expect(error).to.equal(null);
          expect(contents).to.be.a('string');
          expect(contents.indexOf('var value')).to.equal(-1);
          expect(contents.indexOf('var a')).to.not.equal(-1);
          expect(contents.indexOf('module.exports = value')).to.equal(-1);
          expect(contents.indexOf('module.exports = a')).to.not.equal(-1);
          done();
        });
      }
    );
  });
});
<|endoftext|>


<commit_before>"use strict";
/*jshint mocha: true*/
/*eslint-env mocha*/
/*global assert*/

/*eslint-disable max-nested-callbacks*/

describe("interfaces", function () {

    var gpfIEventDispatcher = gpf.interfaces.IEventDispatcher;

    function SampleEventDispatcherWithAddOnly () {
    }

    function SampleEventDispatcherComplete () {
    }

    /**
     * @this bound object
     */
    function fakeAddEventListener (a, b) {
        /*jshint validthis:true*/
        assert(a);
        assert(b);
        return this;
    }

    /**
     * @this bound object
     */
    function fakeRemoveEventListener (a, b) {
        /*jshint validthis:true*/
        assert(a);
        assert(b);
        return this;
    }

    function fakeDispatchEvent (a, b) {
        assert(a);
        assert(b);
        return null;
    }

    SampleEventDispatcherWithAddOnly.prototype = {
        addEventListener: fakeAddEventListener
    };

    SampleEventDispatcherComplete.prototype = new SampleEventDispatcherWithAddOnly();
    SampleEventDispatcherComplete.prototype.removeEventListener = fakeRemoveEventListener;
    SampleEventDispatcherComplete.prototype.dispatchEvent = fakeDispatchEvent;

    describe("gpf.interfaces.isImplementedBy", function () {

        it("verifies that an object implements an interface", function () {
            var test = {
                addEventListener: fakeAddEventListener,
                removeEventListener: fakeRemoveEventListener,
                dispatchEvent: fakeDispatchEvent
            };
            assert(true === gpf.interfaces.isImplementedBy(test, gpfIEventDispatcher));
        });

        it("checks function signatures", function () {
            var test = {
                addEventListener: function (a, b) {
                    return a + b;
                },
                removeEventListener: fakeRemoveEventListener
            };
            assert(false === gpf.interfaces.isImplementedBy(test, gpfIEventDispatcher));
        });

        it("works through inheritance", function () {
            assert(true === gpf.interfaces.isImplementedBy(new SampleEventDispatcherComplete(), gpfIEventDispatcher));
        });

        it("works with classes", function () {
            assert(true === gpf.interfaces.isImplementedBy(SampleEventDispatcherComplete, gpfIEventDispatcher));
        });

    });

    describe("gpf.interfaces.query", function () {

        it("generates an error if interface not available", function () {
            var caught;
            try {
                gpf.interfaces.query({}, gpfIEventDispatcher);
            } catch (e) {
                caught = e;
            }
            assert(null !== caught);
            assert(caught.code === gpf.Error.CODE_INTERFACEEXPECTED);
            assert(caught.code === gpf.Error.interfaceExpected.CODE);
            assert(caught.name === "interfaceExpected");
            assert(caught.message === "Expected interface not implemented: gpf.interfaces.IEventDispatcher");
        });

        it("can also just return null if interface not available", function () {
            assert(null === gpf.interfaces.query({}, gpfIEventDispatcher, false));
        });

        it("retrieves an object for the expected interface", function () {
            var instance = new SampleEventDispatcherComplete(),
                iEventDispatcher = gpf.interfaces.query(instance, gpfIEventDispatcher, false);
            assert(null !== iEventDispatcher);
            assert(instance === iEventDispatcher);
            assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher, gpfIEventDispatcher));
        });

    });

    describe("IUnknown", function () {

        function SampleBuilder () {
        }
        SampleBuilder.prototype.queryInterface = function (iDefinition) {
            if (gpfIEventDispatcher === iDefinition) {
                return new SampleEventDispatcherComplete();
            }
            return null;
        };

        it("exposes queryInterface", function () {
            assert(true === gpf.interfaces.isImplementedBy(SampleBuilder, gpf.interfaces.IUnknown));
        });

        it("is used by gpf.interfaces.query", function () {
            var instance = new SampleBuilder(),
                iEventDispatcher = gpf.interfaces.query(instance, gpfIEventDispatcher, false);
            assert(null !== iEventDispatcher);
            assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher, gpfIEventDispatcher));
        });

    });

    describe("$InterfaceImplement", function () {

        describe("member name", function () {

            var SampleBuilder = gpf.define("SampleBuilder", {
                "[Class]": [gpf.$InterfaceImplement(gpfIEventDispatcher, "_getAswEventDispatcher")],
                "private": {
                    _getAswEventDispatcher: function () {
                        return new SampleEventDispatcherComplete();
                    }
                }
            });

            it("exposes queryInterface", function () {
                assert(true === gpf.interfaces.isImplementedBy(SampleBuilder, gpf.interfaces.IUnknown));
            });

            it("is used by gpf.interfaces.query", function () {
                var instance = new SampleBuilder(),
                    iEventDispatcher = gpf.interfaces.query(instance, gpfIEventDispatcher, false);
                assert(null !== iEventDispatcher);
                assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher, gpfIEventDispatcher));
            });

        });

        describe("builder function", function () {

            function _getAswEventDispatcher (that) {
                assert(null !== that);
                return new SampleEventDispatcherComplete();
            }
            var SampleBuilder = gpf.define("SampleBuilder", {
                "[Class]": [gpf.$InterfaceImplement(gpfIEventDispatcher, _getAswEventDispatcher)]
            });

            it("exposes queryInterface", function () {
                assert(true === gpf.interfaces.isImplementedBy(SampleBuilder, gpf.interfaces.IUnknown));
            });

            it("is used by gpf.interfaces.query", function () {
                var instance = new SampleBuilder(),
                    iEventDispatcher = gpf.interfaces.query(instance, gpfIEventDispatcher, false);
                assert(null !== iEventDispatcher);
                assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher, gpfIEventDispatcher));
            });

        });

    });

});
<commit_msg>Improved coverage<commit_after>"use strict";
/*jshint mocha: true*/
/*eslint-env mocha*/
/*global assert*/

/*eslint-disable max-nested-callbacks*/

describe("interfaces", function () {

    var gpfIEventDispatcher = gpf.interfaces.IEventDispatcher;

    function SampleEventDispatcherWithAddOnly () {
    }

    function SampleEventDispatcherComplete () {
    }

    /**
     * @this bound object
     */
    function fakeAddEventListener (a, b) {
        /*jshint validthis:true*/
        assert(a);
        assert(b);
        return this;
    }

    /**
     * @this bound object
     */
    function fakeRemoveEventListener (a, b) {
        /*jshint validthis:true*/
        assert(a);
        assert(b);
        return this;
    }

    function fakeDispatchEvent (a, b) {
        assert(a);
        assert(b);
        return null;
    }

    SampleEventDispatcherWithAddOnly.prototype = {
        addEventListener: fakeAddEventListener
    };

    SampleEventDispatcherComplete.prototype = new SampleEventDispatcherWithAddOnly();
    SampleEventDispatcherComplete.prototype.removeEventListener = fakeRemoveEventListener;
    SampleEventDispatcherComplete.prototype.dispatchEvent = fakeDispatchEvent;

    describe("gpf.interfaces.isImplementedBy", function () {

        it("verifies that an object implements an interface", function () {
            var test = {
                addEventListener: fakeAddEventListener,
                removeEventListener: fakeRemoveEventListener,
                dispatchEvent: fakeDispatchEvent
            };
            assert(true === gpf.interfaces.isImplementedBy(test, gpfIEventDispatcher));
        });

        it("checks function signatures", function () {
            var test = {
                addEventListener: function (a, b, c) {
                    return a + b + c;
                },
                removeEventListener: fakeRemoveEventListener
            };
            assert(false === gpf.interfaces.isImplementedBy(test, gpfIEventDispatcher));
        });

        it("works through inheritance", function () {
            assert(true === gpf.interfaces.isImplementedBy(new SampleEventDispatcherComplete(), gpfIEventDispatcher));
        });

        it("works with classes", function () {
            assert(true === gpf.interfaces.isImplementedBy(SampleEventDispatcherComplete, gpfIEventDispatcher));
        });

    });

    describe("gpf.interfaces.query", function () {

        it("generates an error if interface not available", function () {
            var caught;
            try {
                gpf.interfaces.query({}, gpfIEventDispatcher);
            } catch (e) {
                caught = e;
            }
            assert(null !== caught);
            assert(caught.code === gpf.Error.CODE_INTERFACEEXPECTED);
            assert(caught.code === gpf.Error.interfaceExpected.CODE);
            assert(caught.name === "interfaceExpected");
            assert(caught.message === "Expected interface not implemented: gpf.interfaces.IEventDispatcher");
        });

        it("can also just return null if interface not available", function () {
            assert(null === gpf.interfaces.query({}, gpfIEventDispatcher, false));
        });

        it("retrieves an object for the expected interface", function () {
            var instance = new SampleEventDispatcherComplete(),
                iEventDispatcher = gpf.interfaces.query(instance, gpfIEventDispatcher, false);
            assert(null !== iEventDispatcher);
            assert(instance === iEventDispatcher);
            assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher, gpfIEventDispatcher));
        });

    });

    describe("IUnknown", function () {

        function SampleBuilder () {
        }
        SampleBuilder.prototype.queryInterface = function (iDefinition) {
            if (gpfIEventDispatcher === iDefinition) {
                return new SampleEventDispatcherComplete();
            }
            return null;
        };

        it("exposes queryInterface", function () {
            assert(true === gpf.interfaces.isImplementedBy(SampleBuilder, gpf.interfaces.IUnknown));
        });

        it("is used by gpf.interfaces.query", function () {
            var instance = new SampleBuilder(),
                iEventDispatcher = gpf.interfaces.query(instance, gpfIEventDispatcher, false);
            assert(null !== iEventDispatcher);
            assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher, gpfIEventDispatcher));
        });

    });

    describe("$InterfaceImplement", function () {

        describe("member name", function () {

            var SampleBuilder = gpf.define("SampleBuilder", {
                "[Class]": [gpf.$InterfaceImplement(gpfIEventDispatcher, "_getAswEventDispatcher")],
                "private": {
                    _getAswEventDispatcher: function () {
                        return new SampleEventDispatcherComplete();
                    }
                }
            });

            it("exposes queryInterface", function () {
                assert(true === gpf.interfaces.isImplementedBy(SampleBuilder, gpf.interfaces.IUnknown));
            });

            it("is used by gpf.interfaces.query", function () {
                var instance = new SampleBuilder(),
                    iEventDispatcher = gpf.interfaces.query(instance, gpfIEventDispatcher, false);
                assert(null !== iEventDispatcher);
                assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher, gpfIEventDispatcher));
            });

        });

        describe("builder function", function () {

            function _getAswEventDispatcher (that) {
                assert(null !== that);
                return new SampleEventDispatcherComplete();
            }
            var SampleBuilder = gpf.define("SampleBuilder", {
                "[Class]": [gpf.$InterfaceImplement(gpfIEventDispatcher, _getAswEventDispatcher)]
            });

            it("exposes queryInterface", function () {
                assert(true === gpf.interfaces.isImplementedBy(SampleBuilder, gpf.interfaces.IUnknown));
            });

            it("is used by gpf.interfaces.query", function () {
                var instance = new SampleBuilder(),
                    iEventDispatcher = gpf.interfaces.query(instance, gpfIEventDispatcher, false);
                assert(null !== iEventDispatcher);
                assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher, gpfIEventDispatcher));
            });

        });

    });

});
<|endoftext|>