<commit_before>import * as http from 'http';
import { parse } from 'url';
import * as zlib from 'zlib';
import * as stream from 'stream';
import { convert } from 'encoding';
import { multipart as Multipart } from 'parted';

export default class TestServer {
	constructor() {
		this.server = http.createServer(this.router);
		this.port = 30001;
		this.hostname = 'localhost';
		this.server.on('error', function(err) {
			console.log(err.stack);
		});
		this.server.on('connection', function(socket) {
			socket.setTimeout(1500);
		});
	}

	start(cb) {
		this.server.listen(this.port, this.hostname, cb);
	}

	stop(cb) {
		this.server.close(cb);
	}

	router(req, res) {
		let p = parse(req.url).pathname;

		if (p === '/hello') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.end('world');
		}

		if (p === '/plain') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.end('text');
		}

		if (p === '/options') {
			res.statusCode = 200;
			res.setHeader('Allow', 'GET, HEAD, OPTIONS');
			res.end('hello world');
		}

		if (p === '/html') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/html');
			res.end('');
		}

		if (p === '/json') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'application/json');
			res.end(JSON.stringify({
				name: 'value'
			}));
		}

		if (p === '/gzip') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.setHeader('Content-Encoding', 'gzip');
			zlib.gzip('hello world', function(err, buffer) {
				res.end(buffer);
			});
		}

		if (p === '/gzip-truncated') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.setHeader('Content-Encoding', 'gzip');
			zlib.gzip('hello world', function(err, buffer) {
				// truncate the CRC checksum and size check at the end of the stream
				res.end(buffer.slice(0, buffer.length - 8));
			});
		}

		if (p === '/deflate') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.setHeader('Content-Encoding', 'deflate');
			zlib.deflate('hello world', function(err, buffer) {
				res.end(buffer);
			});
		}

		if (p === '/deflate-raw') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.setHeader('Content-Encoding', 'deflate');
			zlib.deflateRaw('hello world', function(err, buffer) {
				res.end(buffer);
			});
		}

		if (p === '/sdch') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.setHeader('Content-Encoding', 'sdch');
			res.end('fake sdch string');
		}

		if (p === '/invalid-content-encoding') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.setHeader('Content-Encoding', 'gzip');
			res.end('fake gzip string');
		}

		if (p === '/timeout') {
			setTimeout(function() {
				res.statusCode = 200;
				res.setHeader('Content-Type', 'text/plain');
				res.end('text');
			}, 1000);
		}

		if (p === '/slow') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.write('test');
			setTimeout(function() {
				res.end('test');
			}, 1000);
		}

		if (p === '/cookie') {
			res.statusCode = 200;
			res.setHeader('Set-Cookie', ['a=1', 'b=1']);
			res.end('cookie');
		}

		if (p === '/size/chunk') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			setTimeout(function() {
				res.write('test');
			}, 50);
			setTimeout(function() {
				res.end('test');
			}, 100);
		}

		if (p === '/size/long') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.end('testtest');
		}

		if (p === '/encoding/gbk') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/html');
			res.end(convert('<meta charset="gbk">
中文
', 'gbk'));
		}

		if (p === '/encoding/gb2312') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/html');
			res.end(convert('<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
中文
', 'gb2312'));
		}

		if (p === '/encoding/shift-jis') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/html; charset=Shift-JIS');
			res.end(convert('
日本語
', 'Shift_JIS'));
		}

		if (p === '/encoding/euc-jp') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/xml');
			res.end(convert('<?xml version="1.0" encoding="EUC-JP"?><title>日本語</title>', 'EUC-JP'));
		}

		if (p === '/encoding/utf8') {
			res.statusCode = 200;
			res.end('中文');
		}

		if (p === '/encoding/order1') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'charset=gbk; text/plain');
			res.end(convert('中文', 'gbk'));
		}

		if (p === '/encoding/order2') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain; charset=gbk; qs=1');
			res.end(convert('中文', 'gbk'));
		}

		if (p === '/encoding/chunked') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/html');
			res.setHeader('Transfer-Encoding', 'chunked');
			res.write('a'.repeat(10));
			res.end(convert('<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" />
日本語
', 'Shift_JIS'));
		}

		if (p === '/encoding/invalid') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/html');
			res.setHeader('Transfer-Encoding', 'chunked');
			res.write('a'.repeat(1200));
			res.end(convert('中文', 'gbk'));
		}

		if (p === '/redirect/301') {
			res.statusCode = 301;
			res.setHeader('Location', '/inspect');
			res.end();
		}

		if (p === '/redirect/302') {
			res.statusCode = 302;
			res.setHeader('Location', '/inspect');
			res.end();
		}

		if (p === '/redirect/303') {
			res.statusCode = 303;
			res.setHeader('Location', '/inspect');
			res.end();
		}

		if (p === '/redirect/307') {
			res.statusCode = 307;
			res.setHeader('Location', '/inspect');
			res.end();
		}

		if (p === '/redirect/308') {
			res.statusCode = 308;
			res.setHeader('Location', '/inspect');
			res.end();
		}

		if (p === '/redirect/chain') {
			res.statusCode = 301;
			res.setHeader('Location', '/redirect/301');
			res.end();
		}

		if (p === '/error/redirect') {
			res.statusCode = 301;
			//res.setHeader('Location', '/inspect');
			res.end();
		}

		if (p === '/error/400') {
			res.statusCode = 400;
			res.setHeader('Content-Type', 'text/plain');
			res.end('client error');
		}

		if (p === '/error/404') {
			res.statusCode = 404;
			res.setHeader('Content-Encoding', 'gzip');
			res.end();
		}

		if (p === '/error/500') {
			res.statusCode = 500;
			res.setHeader('Content-Type', 'text/plain');
			res.end('server error');
		}

		if (p === '/error/reset') {
			res.destroy();
		}

		if (p === '/error/json') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'application/json');
			res.end('invalid json');
		}

		if (p === '/no-content') {
			res.statusCode = 204;
			res.end();
		}

		if (p === '/no-content/gzip') {
			res.statusCode = 204;
			res.setHeader('Content-Encoding', 'gzip');
			res.end();
		}

		if (p === '/not-modified') {
			res.statusCode = 304;
			res.end();
		}

		if (p === '/not-modified/gzip') {
			res.statusCode = 304;
			res.setHeader('Content-Encoding', 'gzip');
			res.end();
		}

		if (p === '/inspect') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'application/json');
			let body = '';
			req.on('data', function(c) { body += c });
			req.on('end', function() {
				res.end(JSON.stringify({
					method: req.method,
					url: req.url,
					headers: req.headers,
					body
				}));
			});
		}

		if (p === '/multipart') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'application/json');
			const parser = new Multipart(req.headers['content-type']);
			let body = '';
			parser.on('part', function(field, part) {
				body += field + '=' + part;
			});
			parser.on('end', function() {
				res.end(JSON.stringify({
					method: req.method,
					url: req.url,
					headers: req.headers,
					body: body
				}));
			});
			req.pipe(parser);
		}
	}
}

if (require.main === module) {
	const server = new TestServer;
	server.start(() => {
		console.log(`Server started listening at port ${server.port}`);
	});
}
<commit_msg>fix test server for node 8, which changes keepalive connection handling<commit_after>import * as http from 'http';
import { parse } from 'url';
import * as zlib from 'zlib';
import * as stream from 'stream';
import { convert } from 'encoding';
import { multipart as Multipart } from 'parted';

export default class TestServer {
	constructor() {
		this.server = http.createServer(this.router);
		this.port = 30001;
		this.hostname = 'localhost';
		// node 8 default keepalive timeout is 5000ms
		// make it shorter here as we want to close server quickly at the end of tests
		this.server.keepAliveTimeout = 1000;
		this.server.on('error', function(err) {
			console.log(err.stack);
		});
		this.server.on('connection', function(socket) {
			socket.setTimeout(1500);
		});
	}

	start(cb) {
		this.server.listen(this.port, this.hostname, cb);
	}

	stop(cb) {
		this.server.close(cb);
	}

	router(req, res) {
		let p = parse(req.url).pathname;

		if (p === '/hello') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.end('world');
		}

		if (p === '/plain') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.end('text');
		}

		if (p === '/options') {
			res.statusCode = 200;
			res.setHeader('Allow', 'GET, HEAD, OPTIONS');
			res.end('hello world');
		}

		if (p === '/html') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/html');
			res.end('');
		}

		if (p === '/json') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'application/json');
			res.end(JSON.stringify({
				name: 'value'
			}));
		}

		if (p === '/gzip') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.setHeader('Content-Encoding', 'gzip');
			zlib.gzip('hello world', function(err, buffer) {
				res.end(buffer);
			});
		}

		if (p === '/gzip-truncated') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.setHeader('Content-Encoding', 'gzip');
			zlib.gzip('hello world', function(err, buffer) {
				// truncate the CRC checksum and size check at the end of the stream
				res.end(buffer.slice(0, buffer.length - 8));
			});
		}

		if (p === '/deflate') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.setHeader('Content-Encoding', 'deflate');
			zlib.deflate('hello world', function(err, buffer) {
				res.end(buffer);
			});
		}

		if (p === '/deflate-raw') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.setHeader('Content-Encoding', 'deflate');
			zlib.deflateRaw('hello world', function(err, buffer) {
				res.end(buffer);
			});
		}

		if (p === '/sdch') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.setHeader('Content-Encoding', 'sdch');
			res.end('fake sdch string');
		}

		if (p === '/invalid-content-encoding') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.setHeader('Content-Encoding', 'gzip');
			res.end('fake gzip string');
		}

		if (p === '/timeout') {
			setTimeout(function() {
				res.statusCode = 200;
				res.setHeader('Content-Type', 'text/plain');
				res.end('text');
			}, 1000);
		}

		if (p === '/slow') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.write('test');
			setTimeout(function() {
				res.end('test');
			}, 1000);
		}

		if (p === '/cookie') {
			res.statusCode = 200;
			res.setHeader('Set-Cookie', ['a=1', 'b=1']);
			res.end('cookie');
		}

		if (p === '/size/chunk') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			setTimeout(function() {
				res.write('test');
			}, 50);
			setTimeout(function() {
				res.end('test');
			}, 100);
		}

		if (p === '/size/long') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain');
			res.end('testtest');
		}

		if (p === '/encoding/gbk') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/html');
			res.end(convert('<meta charset="gbk">
中文
', 'gbk'));
		}

		if (p === '/encoding/gb2312') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/html');
			res.end(convert('<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
中文
', 'gb2312'));
		}

		if (p === '/encoding/shift-jis') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/html; charset=Shift-JIS');
			res.end(convert('
日本語
', 'Shift_JIS'));
		}

		if (p === '/encoding/euc-jp') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/xml');
			res.end(convert('<?xml version="1.0" encoding="EUC-JP"?><title>日本語</title>', 'EUC-JP'));
		}

		if (p === '/encoding/utf8') {
			res.statusCode = 200;
			res.end('中文');
		}

		if (p === '/encoding/order1') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'charset=gbk; text/plain');
			res.end(convert('中文', 'gbk'));
		}

		if (p === '/encoding/order2') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/plain; charset=gbk; qs=1');
			res.end(convert('中文', 'gbk'));
		}

		if (p === '/encoding/chunked') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/html');
			res.setHeader('Transfer-Encoding', 'chunked');
			res.write('a'.repeat(10));
			res.end(convert('<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" />
日本語
', 'Shift_JIS'));
		}

		if (p === '/encoding/invalid') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'text/html');
			res.setHeader('Transfer-Encoding', 'chunked');
			res.write('a'.repeat(1200));
			res.end(convert('中文', 'gbk'));
		}

		if (p === '/redirect/301') {
			res.statusCode = 301;
			res.setHeader('Location', '/inspect');
			res.end();
		}

		if (p === '/redirect/302') {
			res.statusCode = 302;
			res.setHeader('Location', '/inspect');
			res.end();
		}

		if (p === '/redirect/303') {
			res.statusCode = 303;
			res.setHeader('Location', '/inspect');
			res.end();
		}

		if (p === '/redirect/307') {
			res.statusCode = 307;
			res.setHeader('Location', '/inspect');
			res.end();
		}

		if (p === '/redirect/308') {
			res.statusCode = 308;
			res.setHeader('Location', '/inspect');
			res.end();
		}

		if (p === '/redirect/chain') {
			res.statusCode = 301;
			res.setHeader('Location', '/redirect/301');
			res.end();
		}

		if (p === '/error/redirect') {
			res.statusCode = 301;
			//res.setHeader('Location', '/inspect');
			res.end();
		}

		if (p === '/error/400') {
			res.statusCode = 400;
			res.setHeader('Content-Type', 'text/plain');
			res.end('client error');
		}

		if (p === '/error/404') {
			res.statusCode = 404;
			res.setHeader('Content-Encoding', 'gzip');
			res.end();
		}

		if (p === '/error/500') {
			res.statusCode = 500;
			res.setHeader('Content-Type', 'text/plain');
			res.end('server error');
		}

		if (p === '/error/reset') {
			res.destroy();
		}

		if (p === '/error/json') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'application/json');
			res.end('invalid json');
		}

		if (p === '/no-content') {
			res.statusCode = 204;
			res.end();
		}

		if (p === '/no-content/gzip') {
			res.statusCode = 204;
			res.setHeader('Content-Encoding', 'gzip');
			res.end();
		}

		if (p === '/not-modified') {
			res.statusCode = 304;
			res.end();
		}

		if (p === '/not-modified/gzip') {
			res.statusCode = 304;
			res.setHeader('Content-Encoding', 'gzip');
			res.end();
		}

		if (p === '/inspect') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'application/json');
			let body = '';
			req.on('data', function(c) { body += c });
			req.on('end', function() {
				res.end(JSON.stringify({
					method: req.method,
					url: req.url,
					headers: req.headers,
					body
				}));
			});
		}

		if (p === '/multipart') {
			res.statusCode = 200;
			res.setHeader('Content-Type', 'application/json');
			const parser = new Multipart(req.headers['content-type']);
			let body = '';
			parser.on('part', function(field, part) {
				body += field + '=' + part;
			});
			parser.on('end', function() {
				res.end(JSON.stringify({
					method: req.method,
					url: req.url,
					headers: req.headers,
					body: body
				}));
			});
			req.pipe(parser);
		}
	}
}

if (require.main === module) {
	const server = new TestServer;
	server.start(() => {
		console.log(`Server started listening at port ${server.port}`);
	});
}
<|endoftext|>


<commit_before>const assert = require('assert');

const jwcrypto = require('jwcrypto');
const request = require('request');

const app = require('../server');
const mockid = require('./lib/mockid');

const BASE_URL = 'http://localhost:3033';
const TEST_EMAIL = 'hikingfan@gmail.com';

/* globals describe, before, after, it */

describe('HTTP Endpoints', function () {
  var server;

  before(function (done) {
    app.setOpenIDRP(mockid({
      url: 'http://openid.example',
      result: {
        authenticated: true,
        email: TEST_EMAIL
      }
    }));

    server = app.listen(3033, undefined, undefined, done);
  });

  after(function () {
    server.close();
  });

  describe('/__heartbeat__', function () {
    var url = BASE_URL + '/__heartbeat__';
    var res;
    var body;

    before(function (done) {
      request.get(url, function (err, _res, _body) {
        res = _res;
        body = _body;
        done(err);
      });
    });

    it('should respond to GET', function () {
      assert.equal(res.statusCode, 200);
    });

    it('should have an "ok" body', function () {
      assert.equal(body, 'ok');
    });
  });

  describe('/.well-known/browserid', function () {
    var url = BASE_URL + '/.well-known/browserid';
    var res;
    var body;

    before(function (done) {
      request.get(url, function (err, _res, _body) {
        res = _res;
        body = _body;
        done(err);
      });
    });

    it('should respond to GET', function () {
      assert.equal(res.statusCode, 200);
    });

    it('should use application/json', function () {
      var contentType = res.headers['content-type'].split(';')[0];
      assert.equal(contentType, 'application/json');
    });

    it('should be valid JSON', function () {
      assert.doesNotThrow(function () { JSON.parse(body); });
    });

    it('should contain all necessary parameters', function () {
      var doc = JSON.parse(body);
      assert.equal(doc.authentication, '/authenticate');
      assert.equal(doc.provisioning, '/provision');
      assert('public-key' in doc);
    });

    it('should contain a valid public key', function () {
      var doc = JSON.parse(body);
      var pubKey = JSON.stringify(doc['public-key']);
      assert(jwcrypto.loadPublicKey(pubKey));
    });
  });

  describe('/provision', function () {
    var url = BASE_URL + '/provision';
    url; // Make JSHint shut up for the moment...
    it('should have tests');
  });

  describe('/provision/certify', function () {
    var url = BASE_URL + '/provision/certify';
    describe('well-formed requests', function () {
      var pubkey;
      var csrf;

      before(function (done) {
        // Generate a public key for the signing request
        var keyOpts = { algorithm: 'RS', keysize: 64 };
        jwcrypto.generateKeypair(keyOpts, function (err, keypair) {
          pubkey = keypair.publicKey.serialize();
          done(err);
        });
      });

      before(function (done) {
        // Get a claim cookie
        var options = {
          qs: { email: 'hikingfan@gmail.com' },
          followRedirect: false
        };
        var url = BASE_URL + '/authenticate/forward';
        request.get(url, options, function (err) {
          done(err);
        });
      });

      before(function (done) {
        // Get a certify cookie
        var url = BASE_URL + '/authenticate/verify';
        request.get(url, function (err) { done(err); });
      });

      before(function (done) {
        // Get a CSRF token for the request
        request.get(BASE_URL + '/provision', function(err, res, body) {
          var re = /<input type="hidden" id="csrf" value="([^"]+)"\/>/;
          csrf = body.match(re)[1];
          done(err);
        });
      });

      it('should have a csrf token', function () {
        assert(csrf);
      });

      it('should sign certificates', function (done) {
        var options = {
          headers: { 'X-CSRF-Token': csrf },
          json: { email: TEST_EMAIL, pubkey: pubkey, duration: 5 * 60 * 1000 }
        };

        request.post(url, options, function(err, res, body) {
          assert(body.cert);
          done(err);
        });
      });
    });

    describe('malformed requests', function () {
      it('should have tests');
    });
  });

  describe('/authenticate', function () {
    var url = BASE_URL + '/authenticate';
    url; // Make JSHint shut up for the moment...
    it('should have tests');
  });

  describe('/authenticate/forward', function () {
    var url = BASE_URL + '/authenticate/forward';

    describe('well-formed requests', function () {
      var options = {
        qs: { email: 'hikingfan@gmail.com' },
        followRedirect: false
      };
      var res;
      var body;

      before(function (done) {
        request.get(url, options, function (err, _res, _body) {
          res = _res;
          body = _body;
          done(err);
        });
      });

      it('should respond to GET with a redirect', function () {
        assert.equal(res.statusCode, 302);
      });

      it('should redirect to the OpenID endpoint', function () {
        assert.equal(res.headers.location, 'http://openid.example');
      });
    });

    describe('malformed requests', function () {
      it('should fail on GET for non-google addresses', function (done) {
        var options = {
          qs: { email: 'hikingfan@example.invalid' },
          followRedirect: false
        };

        request.get(url, options, function (err, res) {
          assert.equal(res.statusCode, 500);
          done(err);
        });
      });

      it('should fail on GET if no email is provided', function (done) {
        var options = {
          qs: { },
          followRedirect: false
        };

        request.get(url, options, function (err, res) {
          assert.equal(res.statusCode, 500);
          done(err);
        });
      });
    });
  });

  describe('/authenticate/verify', function () {
    var url = BASE_URL + '/authenticate/verify';
    url; // Make JSHint shut up for the moment...
    it('should have tests');
  });
});
<commit_msg>Test /provision/certify by forging cookies<commit_after>const assert = require('assert');

const clientSessions = require('client-sessions');
const jwcrypto = require('jwcrypto');
const request = require('request');

const app = require('../server');
const config = require('../lib/config');
const mockid = require('./lib/mockid');

const BASE_URL = 'http://localhost:3033';
const TEST_EMAIL = 'hikingfan@gmail.com';

/* globals describe, before, after, it */

describe('HTTP Endpoints', function () {
  var server;

  before(function (done) {
    app.setOpenIDRP(mockid({
      url: 'http://openid.example',
      result: {
        authenticated: true,
        email: TEST_EMAIL
      }
    }));

    server = app.listen(3033, undefined, undefined, done);
  });

  after(function () {
    server.close();
  });

  describe('/__heartbeat__', function () {
    var url = BASE_URL + '/__heartbeat__';
    var res;
    var body;

    before(function (done) {
      request.get(url, function (err, _res, _body) {
        res = _res;
        body = _body;
        done(err);
      });
    });

    it('should respond to GET', function () {
      assert.equal(res.statusCode, 200);
    });

    it('should have an "ok" body', function () {
      assert.equal(body, 'ok');
    });
  });

  describe('/.well-known/browserid', function () {
    var url = BASE_URL + '/.well-known/browserid';
    var res;
    var body;

    before(function (done) {
      request.get(url, function (err, _res, _body) {
        res = _res;
        body = _body;
        done(err);
      });
    });

    it('should respond to GET', function () {
      assert.equal(res.statusCode, 200);
    });

    it('should use application/json', function () {
      var contentType = res.headers['content-type'].split(';')[0];
      assert.equal(contentType, 'application/json');
    });

    it('should be valid JSON', function () {
      assert.doesNotThrow(function () { JSON.parse(body); });
    });

    it('should contain all necessary parameters', function () {
      var doc = JSON.parse(body);
      assert.equal(doc.authentication, '/authenticate');
      assert.equal(doc.provisioning, '/provision');
      assert('public-key' in doc);
    });

    it('should contain a valid public key', function () {
      var doc = JSON.parse(body);
      var pubKey = JSON.stringify(doc['public-key']);
      assert(jwcrypto.loadPublicKey(pubKey));
    });
  });

  describe('/provision', function () {
    var url = BASE_URL + '/provision';
    url; // Make JSHint shut up for the moment...
    it('should have tests');
  });

  describe('/provision/certify', function () {
    var url = BASE_URL + '/provision/certify';
    describe('well-formed requests', function () {
      var pubkey;

      before(function (done) {
        // Generate a public key for the signing request
        var keyOpts = { algorithm: 'RS', keysize: 64 };
        jwcrypto.generateKeypair(keyOpts, function (err, keypair) {
          pubkey = keypair.publicKey.serialize();
          done(err);
        });
      });

      var cookie;
      before(function () {
        // Forge a session cookie
        var cookieOptions = {
          cookieName: 'session',
          secret: config.get('secret')
        };
        var cookieContents = { _csrf: 'foo', proven: TEST_EMAIL };

        cookie = clientSessions.util.encode(cookieOptions, cookieContents);
      });

      it('should sign certificates', function (done) {
        var jar = request.jar();
        jar.add(request.cookie('session=' + cookie));
        var options = {
          headers: { 'X-CSRF-Token': 'foo' },
          json: { email: TEST_EMAIL, pubkey: pubkey, duration: 5 * 60 * 1000 },
          jar: jar
        };

        request.post(url, options, function(err, res, body) {
          assert(body.cert);
          done(err);
        });
      });
    });

    describe('malformed requests', function () {
      it('should have tests');
    });
  });

  describe('/authenticate', function () {
    var url = BASE_URL + '/authenticate';
    url; // Make JSHint shut up for the moment...
    it('should have tests');
  });

  describe('/authenticate/forward', function () {
    var url = BASE_URL + '/authenticate/forward';

    describe('well-formed requests', function () {
      var options = {
        qs: { email: 'hikingfan@gmail.com' },
        followRedirect: false
      };
      var res;
      var body;

      before(function (done) {
        request.get(url, options, function (err, _res, _body) {
          res = _res;
          body = _body;
          done(err);
        });
      });

      it('should respond to GET with a redirect', function () {
        assert.equal(res.statusCode, 302);
      });

      it('should redirect to the OpenID endpoint', function () {
        assert.equal(res.headers.location, 'http://openid.example');
      });
    });

    describe('malformed requests', function () {
      it.skip('should fail on GET for non-google addresses', function (done) {
        var options = {
          qs: { email: 'hikingfan@example.invalid' },
          followRedirect: false
        };

        request.get(url, options, function (err, res) {
          assert.equal(res.statusCode, 500);
          done(err);
        });
      });

      it('should fail on GET if no email is provided', function (done) {
        var options = {
          qs: { },
          followRedirect: false
        };

        request.get(url, options, function (err, res) {
          assert.equal(res.statusCode, 500);
          done(err);
        });
      });
    });
  });

  describe('/authenticate/verify', function () {
    var url = BASE_URL + '/authenticate/verify';
    url; // Make JSHint shut up for the moment...
    it('should have tests');
  });
});
<|endoftext|>


<commit_before>var tape = require('tape')
var Stream = require('../')
var S = require('../state')
var pull = require('pull-stream')

function Peer (logs, onRequest) {
  logs._append = logs._append || []

  function onAppend (msg) {
    for(var i = 0; i < logs._append.length; i++)
      logs._append[i](msg)
  }

  return function (cb) {
    var states = {}
    for(var k in logs)
      if(k[0] != '_')
        states[k] = logs[k].length

    var stream = Stream(
      function get (id, seq, cb) {
        cb(null, logs[id][seq - 1])
      },
      function append (msg, cb) {
        if(logs[msg.author] && msg.sequence == logs[msg.author].length + 1) {
          logs[msg.author].push(msg)
          onAppend(msg)
          cb()
        }
        else cb(new Error('could not append'))
      }
    ) ({
        seqs: states,
        onChange: console.log,
        onRequest: onRequest
      },
      cb)

    logs._append.push(stream.onAppend)

    return stream
  }
}

var alice = [
  {author: 'alice', sequence: 1, content: 'foo'},
  {author: 'alice', sequence: 2, content: 'bar'},
  {author: 'alice', sequence: 3, content: 'baz'}
]
var bob = [
  {author: 'bob', sequence: 1, content: 'X'},
  {author: 'bob', sequence: 2, content: 'Y'},
  {author: 'bob', sequence: 3, content: 'Z'}
]

var bob = [
  {author: 'charles', sequence: 1, content: 'L'},
  {author: 'charles', sequence: 2, content: 'M'},
  {author: 'charles', sequence: 3, content: 'N'},
  {author: 'charles', sequence: 4, content: 'O'},
  {author: 'charles', sequence: 5, content: 'P'},
]

tape('two peers', function (t) {

  var alice_db, bob_db
  var alice_stream = Peer(alice_db = {alice: alice, bob: []}) ()
  var bob_stream = Peer(bob_db = {alice: [], bob: bob}) ()

  function log (name) {
    return pull.through(function (data) {
      console.log(name, data)
    })
  }

  pull(
    alice_stream,
    log('a->b'),
    bob_stream,
    log('b->a'),
    alice_stream
  )

  delete alice_db._append
  delete bob_db._append
  console.log(alice_db)
  console.log(bob_db)

  t.deepEqual(alice_stream.progress().sync, bob_stream.progress().sync)

  t.deepEqual(alice_db, bob_db, 'databases are consistent')
  t.end()
})

tape('three peers, two streams', function (t) {

  var alice_db = {alice: alice, bob: []}
  var bob_db = {alice: [], bob: bob}
  var charles_db = {alice: alice.slice(0, 2), bob: bob.slice(0, 1)}

  var alice_stream = Peer(alice_db) ()
  var bob_stream = Peer(bob_db) ()
  var bob_stream2 = Peer(bob_db) ()
  var charles_stream = Peer(charles_db) ()

  function log (name) {
    return pull.through(function (data) {
      console.log(name, data)
    })
  }

  pull(
    alice_stream,
    log('a->b'),
    bob_stream,
    log('b->a'),
    alice_stream
  )

  pull(
    bob_stream2,
    log('b->c'),
    charles_stream,
    log('b->c'),
    bob_stream2
  )

  delete alice_db._append
  delete bob_db._append
  delete charles_db._append

  console.log(alice_db)
  console.log(bob_db)
  console.log(charles_db)

  t.deepEqual(alice_db, bob_db, 'databases are consistent')
  t.deepEqual(alice_db, charles_db, 'databases are consistent')
  t.end()
})

tape('three peers, four streams', function (t) {

  var alice_db = {alice: alice, bob: []}
  var bob_db = {alice: [], bob: bob}
  var charles_db = {alice: alice.slice(0, 2), bob: bob.slice(0, 1)}

  var alice_stream = Peer(alice_db) ()
  var alice_stream2 = Peer(alice_db) ()
  var bob_stream = Peer(bob_db) ()
  var bob_stream2 = Peer(bob_db) ()
  var charles_stream = Peer(charles_db) ()
  var charles_stream2 = Peer(charles_db) ()

  function log (name) {
    return pull.through(function (data) {
      console.log(name, data)
    })
  }

  pull(
    alice_stream,
    log('a->b'),
    bob_stream,
    log('b->a'),
    alice_stream
  )

  pull(
    bob_stream2,
    log('b->c'),
    charles_stream,
    log('c->b'),
    bob_stream2
  )

  pull(
    alice_stream2,
    log('a->c'),
    charles_stream2,
    log('c->a'),
    alice_stream2
  )

  delete alice_db._append
  delete bob_db._append
  delete charles_db._append

  console.log(alice_db)
  console.log(bob_db)
  console.log(charles_db)

  t.deepEqual(alice_db, bob_db, 'databases are consistent')
  t.deepEqual(alice_db, charles_db, 'databases are consistent')
  t.end()
})

tape('source errors', function (t) {

  var create = Peer({alice: alice, bob: []})

  var err = new Error('test error')
  pull(
    pull.error(err),
    create(function (_err) {
      t.equal(_err, err)
      t.end()
    })
  )

})

tape('sink errors', function (t) {

  var create = Peer({alice: alice, bob: []})

  var err = new Error('test error')
    create(function (_err) {
      t.equal(_err, err)
      t.end()
    }).source(err, function (_err) {
      t.equal(_err, err)
    })

})

tape('stream when one peer does not follow', function (t) {
  var alice_db = {alice: alice}
  var bob_db = {alice: [], bob: bob}

  var alice_stream = Peer(alice_db, function (bob_id, seq) {
    t.equal(bob_id, 'bob')
    t.equal(seq, 3)
    bob_requested = true
  }) ()
  var bob_stream = Peer(bob_db, function () {}) ()

  pull(
    alice_stream,
    bob_stream,
    alice_stream
  )

  t.deepEqual(alice_db.alice, bob_db.alice, 'bob has replicated alice')
  t.notDeepEqual(alice_db.bob, bob_db.bob, 'alice has not replicated bob')
  t.ok(bob_requested)
  console.log(alice_stream.progress())
  alice_db.bob = []
  alice_stream.request('bob', 0)
  t.deepEqual(alice_db.bob, bob_db.bob)
  console.log(alice_stream.progress())
  console.log(alice_db)
  t.end()
})

tape('stream when one peer does not follow', function (t) {
  var alice_db = {alice: alice}
  var bob_db = {alice: [], bob: bob}

  var alice_stream = Peer(alice_db, function (bob_id, seq) {
    t.equal(bob_id, 'bob')
    t.equal(seq, 3)
    bob_requested = true
  }) ()
  var bob_stream = Peer(bob_db, function () {}) ()

  pull(
    alice_stream,
    bob_stream,
    alice_stream
  )

  t.ok(bob_requested)
  t.deepEqual(alice_db.alice, bob_db.alice, 'bob has replicated alice')
  t.notDeepEqual(alice_db.bob, bob_db.bob, 'alice has not replicated bob')

  console.log(alice_stream.progress())
  alice_db.bob = []
  alice_stream.request('bob', -1)
  t.notDeepEqual(alice_db.bob, bob_db.bob, 'alice has not replicated bob')

  console.log(alice_stream.progress())
  console.log(alice_db)
  t.end()
})

tape('alice blocks bob', function (t) {
  var alice_db = {alice: alice, bob: []}
  var bob_db = {alice: [], bob: bob}

  var alice_stream = Peer(alice_db) ()
  var bob_stream = Peer(bob_db) ()

  pull(
    alice_stream,
    pull.through(function (data) { console.log('alice>>', data) }),
    bob_stream,
    pull.through(function (data) { console.log('bob>>', data) }),
    alice_stream
  )
  console.log('REPLICATED', alice_stream.progress())

//  t.ok(bob_requested)
//  t.deepEqual(alice_db.alice, bob_db.alice, 'bob has replicated alice')
//  t.deepEqual(alice_db.bob, bob_db.bob, 'alice has replicated bob')
//
//  console.log(alice_stream.progress())

  t.deepEqual(
    alice_stream.progress(),
    {current: 10, start: 0, target: 10}
//    { sync: 2, feeds: 2, recv: 0, send: 0, total: 3, unknown: 0 }
  )

  alice_stream.request('bob', -1)
  var msg = {author: 'bob', sequence: 4, content: 'BLOCKED'}
  bob_db.bob.push(msg)
  bob_stream.onAppend(msg)

  var p = alice_stream.progress()
  console.log(p)
  t.equal(p.current, p.target)
  t.ok(p.target > 0)

  t.end()
})

return
tape('alice streams from bob and charles', function (t) {
  //note, bob and
  var alice_db = {alice: alice, bob: [], charles: charles}
  var bob_db = {alice: [], bob: bob, charles: []}
  var charles_db = {alice: [], bob: bob, charles: charles}

  var alice_stream = Peer(alice_db) ()
  var alice_stream2 = Peer(alice_db) ()
  var bob_stream = Peer(bob_db) ()
  var charles_stream = Peer(charles_db) ()

  pull(
    alice_stream,
    pull.through(function (data) { console.log('alice>>', data) }),
    bob_stream,
    pull.through(function (data) { console.log('bob>>', data) }),
    alice_stream
  )

  pull(
    alice_stream2,
    pull.through(function (data) { console.log('alice2>>', data) }),
    charles_stream,
    pull.through(function (data) { console.log('charles>>', data) }),
    alice_stream2
  )

  console.log('REPLICATED', alice_stream.progress())

//  t.ok(bob_requested)
//  t.deepEqual(alice_db.alice, bob_db.alice, 'bob has replicated alice')
//  t.deepEqual(alice_db.bob, bob_db.bob, 'alice has replicated bob')
//
//  console.log(alice_stream.progress())

    console.log(alice_db)

//  t.deepEqual(
//    alice_stream.progress(),
//    {current: 10, start: 0, target: 10}
////    { sync: 2, feeds: 2, recv: 0, send: 0, total: 3, unknown: 0 }
//  )
//
//  alice_stream.request('bob', -1)
//  var msg = {author: 'bob', sequence: 4, content: 'BLOCKED'}
//  bob_db.bob.push(msg)
//  bob_stream.onAppend(msg)
//
//  var p = alice_stream.progress()
//  console.log(p)
//  t.equal(p.current, p.target)
//  t.ok(p.target > 0)
//
  t.end()
})

<commit_msg>tidy up test/stream<commit_after>var tape = require('tape')
var Stream = require('../')
var S = require('../state')
var pull = require('pull-stream')

function Peer (logs, onRequest) {
  logs._append = logs._append || []

  function onAppend (msg) {
    for(var i = 0; i < logs._append.length; i++)
      logs._append[i](msg)
  }

  return function (cb) {
    var states = {}
    for(var k in logs)
      if(k[0] != '_')
        states[k] = logs[k].length

    var stream = Stream(
      function get (id, seq, cb) {
        cb(null, logs[id][seq - 1])
      },
      function append (msg, cb) {
        if(logs[msg.author] && msg.sequence == logs[msg.author].length + 1) {
          logs[msg.author].push(msg)
          onAppend(msg)
          cb()
        }
        else cb(new Error('could not append'))
      }
    ) ({
        seqs: states,
        onChange: console.log,
        onRequest: onRequest
      },
      cb)

    logs._append.push(stream.onAppend)

    return stream
  }
}

var alice = [
  {author: 'alice', sequence: 1, content: 'foo'},
  {author: 'alice', sequence: 2, content: 'bar'},
  {author: 'alice', sequence: 3, content: 'baz'}
]
var bob = [
  {author: 'bob', sequence: 1, content: 'X'},
  {author: 'bob', sequence: 2, content: 'Y'},
  {author: 'bob', sequence: 3, content: 'Z'}
]

var charles = [
  {author: 'charles', sequence: 1, content: 'L'},
  {author: 'charles', sequence: 2, content: 'M'},
  {author: 'charles', sequence: 3, content: 'N'},
  {author: 'charles', sequence: 4, content: 'O'},
  {author: 'charles', sequence: 5, content: 'P'},
]

tape('two peers', function (t) {

  var alice_db, bob_db
  var alice_stream = Peer(alice_db = {alice: alice, bob: []}) ()
  var bob_stream = Peer(bob_db = {alice: [], bob: bob}) ()

  function log (name) {
    return pull.through(function (data) {
      console.log(name, data)
    })
  }

  pull(
    alice_stream,
    log('a->b'),
    bob_stream,
    log('b->a'),
    alice_stream
  )

  delete alice_db._append
  delete bob_db._append
  console.log(alice_db)
  console.log(bob_db)

  t.deepEqual(alice_stream.progress().sync, bob_stream.progress().sync)

  t.deepEqual(alice_db, bob_db, 'databases are consistent')
  t.end()
})

tape('three peers, two streams', function (t) {

  var alice_db = {alice: alice, bob: []}
  var bob_db = {alice: [], bob: bob}
  var charles_db = {alice: alice.slice(0, 2), bob: bob.slice(0, 1)}

  var alice_stream = Peer(alice_db) ()
  var bob_stream = Peer(bob_db) ()
  var bob_stream2 = Peer(bob_db) ()
  var charles_stream = Peer(charles_db) ()

  function log (name) {
    return pull.through(function (data) {
      console.log(name, data)
    })
  }

  pull(
    alice_stream,
    log('a->b'),
    bob_stream,
    log('b->a'),
    alice_stream
  )

  pull(
    bob_stream2,
    log('b->c'),
    charles_stream,
    log('b->c'),
    bob_stream2
  )

  delete alice_db._append
  delete bob_db._append
  delete charles_db._append

  console.log(alice_db)
  console.log(bob_db)
  console.log(charles_db)

  t.deepEqual(alice_db, bob_db, 'databases are consistent')
  t.deepEqual(alice_db, charles_db, 'databases are consistent')
  t.end()
})

tape('three peers, four streams', function (t) {

  var alice_db = {alice: alice, bob: []}
  var bob_db = {alice: [], bob: bob}
  var charles_db = {alice: alice.slice(0, 2), bob: bob.slice(0, 1)}

  var alice_stream = Peer(alice_db) ()
  var alice_stream2 = Peer(alice_db) ()
  var bob_stream = Peer(bob_db) ()
  var bob_stream2 = Peer(bob_db) ()
  var charles_stream = Peer(charles_db) ()
  var charles_stream2 = Peer(charles_db) ()

  function log (name) {
    return pull.through(function (data) {
      console.log(name, data)
    })
  }

  pull(
    alice_stream,
    log('a->b'),
    bob_stream,
    log('b->a'),
    alice_stream
  )

  pull(
    bob_stream2,
    log('b->c'),
    charles_stream,
    log('c->b'),
    bob_stream2
  )

  pull(
    alice_stream2,
    log('a->c'),
    charles_stream2,
    log('c->a'),
    alice_stream2
  )

  delete alice_db._append
  delete bob_db._append
  delete charles_db._append

  console.log(alice_db)
  console.log(bob_db)
  console.log(charles_db)

  t.deepEqual(alice_db, bob_db, 'databases are consistent')
  t.deepEqual(alice_db, charles_db, 'databases are consistent')
  t.end()
})

tape('source errors', function (t) {

  var create = Peer({alice: alice, bob: []})

  var err = new Error('test error')
  pull(
    pull.error(err),
    create(function (_err) {
      t.equal(_err, err)
      t.end()
    })
  )

})

tape('sink errors', function (t) {

  var create = Peer({alice: alice, bob: []})

  var err = new Error('test error')
    create(function (_err) {
      t.equal(_err, err)
      t.end()
    }).source(err, function (_err) {
      t.equal(_err, err)
    })

})

tape('stream when one peer does not follow', function (t) {
  var alice_db = {alice: alice}
  var bob_db = {alice: [], bob: bob}

  var alice_stream = Peer(alice_db, function (bob_id, seq) {
    t.equal(bob_id, 'bob')
    t.equal(seq, 3)
    bob_requested = true
  }) ()
  var bob_stream = Peer(bob_db, function () {}) ()

  pull(
    alice_stream,
    bob_stream,
    alice_stream
  )

  t.deepEqual(alice_db.alice, bob_db.alice, 'bob has replicated alice')
  t.notDeepEqual(alice_db.bob, bob_db.bob, 'alice has not replicated bob')
  t.ok(bob_requested)
  console.log(alice_stream.progress())
  alice_db.bob = []
  alice_stream.request('bob', 0)
  t.deepEqual(alice_db.bob, bob_db.bob)
  console.log(alice_stream.progress())
  console.log(alice_db)
  t.end()
})

tape('stream when one peer does not follow', function (t) {
  var alice_db = {alice: alice}
  var bob_db = {alice: [], bob: bob}

  var alice_stream = Peer(alice_db, function (bob_id, seq) {
    t.equal(bob_id, 'bob')
    t.equal(seq, 3)
    bob_requested = true
  }) ()
  var bob_stream = Peer(bob_db, function () {}) ()

  pull(
    alice_stream,
    bob_stream,
    alice_stream
  )

  t.ok(bob_requested)
  t.deepEqual(alice_db.alice, bob_db.alice, 'bob has replicated alice')
  t.notDeepEqual(alice_db.bob, bob_db.bob, 'alice has not replicated bob')

  console.log(alice_stream.progress())
  alice_db.bob = []
  alice_stream.request('bob', -1)
  t.notDeepEqual(alice_db.bob, bob_db.bob, 'alice has not replicated bob')

  console.log(alice_stream.progress())
  console.log(alice_db)
  t.end()
})

tape('alice blocks bob', function (t) {
  var alice_db = {alice: alice, bob: []}
  var bob_db = {alice: [], bob: bob}

  var alice_stream = Peer(alice_db) ()
  var bob_stream = Peer(bob_db) ()

  pull(
    alice_stream,
    pull.through(function (data) { console.log('alice>>', data) }),
    bob_stream,
    pull.through(function (data) { console.log('bob>>', data) }),
    alice_stream
  )
  console.log('REPLICATED', alice_stream.progress())

//  t.ok(bob_requested)
//  t.deepEqual(alice_db.alice, bob_db.alice, 'bob has replicated alice')
//  t.deepEqual(alice_db.bob, bob_db.bob, 'alice has replicated bob')
//
//  console.log(alice_stream.progress())

  t.deepEqual(
    alice_stream.progress(),
    {current: 10, start: 0, target: 10}
//    { sync: 2, feeds: 2, recv: 0, send: 0, total: 3, unknown: 0 }
  )

  alice_stream.request('bob', -1)
  var msg = {author: 'bob', sequence: 4, content: 'BLOCKED'}
  bob_db.bob.push(msg)
  bob_stream.onAppend(msg)

  var p = alice_stream.progress()
  console.log(p)
  t.equal(p.current, p.target)
  t.ok(p.target > 0)

  t.end()
})

tape('alice streams from bob and charles', function (t) {
  //note, bob and
  var alice_db = {alice: alice, bob: [], charles: []}
  var bob_db = {alice: [], bob: bob, charles: []}
  var charles_db = {alice: [], bob: bob, charles: charles}

  var alice_stream = Peer(alice_db) ()
  var alice_stream2 = Peer(alice_db) ()
  var bob_stream = Peer(bob_db) ()
  var charles_stream = Peer(charles_db) ()

  pull(
    alice_stream,
    pull.through(function (data) { console.log('AB>', data) }),
    bob_stream,
    pull.through(function (data) { console.log('BA>', data) }),
    alice_stream
  )

  pull(
    alice_stream2,
    pull.through(function (data) { console.log('AC>', data) }),
    charles_stream,
    pull.through(function (data) { console.log('CA>', data) }),
    alice_stream2
  )

  console.log('REPLICATED', alice_stream.progress())

  t.end()
})

<|endoftext|>


<commit_before>'use strict';

const classAsString = 'MaterialFragment';
const cssFragment = 'mdl-fragment';
const selFragment = `.${cssFragment}`;

(() => {
/**
 * Do not move this test to any other place and
 * from the index.html
 */
onload_test(function(e) {
  var fragment = document.querySelector(selFragment);

  assert_true(fragment.dataset.upgraded.includes(classAsString));
  this.done();
}, "MDL upgrades the component from the Body");

/**
 * Do not move this test to any other place and
 * from the index.html
 */
onload_test(function(e) {
  var fragment = document.querySelector(selFragment).MaterialFragment;

  assert_true(fragment instanceof MaterialFragment);

  document.querySelector(selFragment).remove();
  this.done();
}, "Check the API");

/**
 * Do a simple import from absolute path
 */
onload_test(function(e) {
  // [setup]
  var fragment = document.createElement('div');
  fragment.setAttribute('src', '/test/fixtures/fragment1.html');
  fragment.classList.add(cssFragment);
  fragment.addEventListener('load', this.step_func((e) => {
    // [verify]
    var fragment1 = fragment.querySelector('#fragment1');
    assert_true(fragment1 instanceof HTMLElement);
    assert_equals(fragment1.textContent, 'Fragment 1');
    assert_equals(e.detail.fragment, fragment);

    // [teardown]
    fragment.remove();
    this.done();
  }));

  // [run]
  document.body.appendChild(fragment);
  componentHandler.upgradeElement(fragment);
}, "Import from src='/test/fixtures/fragment1.html' absolute path, default insertion");

/**
 * Do a simple import from relative path
 */
onload_test(function(e) {
  // [setup]
  var fragment = document.createElement('div');
  fragment.setAttribute('src', 'fixtures/fragment1.html');
  fragment.classList.add(cssFragment);
  fragment.addEventListener('load', this.step_func(() => {
    // [verify]
    var fragment1 = fragment.querySelector('#fragment1');
    assert_true(fragment1 instanceof HTMLElement);
    assert_equals(fragment1.textContent, 'Fragment 1');

    // [teardown]
    fragment.remove();
    this.done();
  }));

  // [run]
  document.body.appendChild(fragment);
  componentHandler.upgradeElement(fragment);
}, "Import from src='/test/fixtures/fragment1.html' relative path, default insertion");

/**
 * Do a nested import from absolute path
 */
onload_test(function(e) {
  // [setup]
  var fragment = document.createElement('div');
  fragment.setAttribute('src', '/test/fixtures/fragment2.html');
  fragment.classList.add(cssFragment);
  fragment.addEventListener('load', this.step_func((e) => {
    // [verify]
    var fragment1 = fragment.querySelector(selFragment);
    var fragment2 = fragment.querySelector('#fragment2');
    assert_true(fragment2 instanceof HTMLElement);
    assert_true(fragment1 instanceof HTMLElement);
    assert_equals(fragment2.textContent, 'Fragment 2');
    assert_equals(e.detail.fragment, fragment);

    fragment1.addEventListener('load', this.step_func((e) => {
      var fragment1_ = fragment.querySelector('#fragment1');

      assert_true(fragment1_ instanceof HTMLElement);
      assert_equals(fragment1_.textContent, 'Fragment 1');
      assert_equals(e.detail.fragment, fragment1);

      // [teardown]
      fragment.remove();
      this.done();
    }));
  }));

  // [run]
  document.body.appendChild(fragment);
  componentHandler.upgradeElement(fragment);
}, "Import from src='/test/fixtures/fragment2.html' absolute path, nested, default insertion");

/**
 * Do a nested import from relative path
 */
onload_test(function(e) {
  // [setup]
  var fragment = document.createElement('div');
  fragment.setAttribute('src', 'fixtures/fragment3.html');
  fragment.classList.add(cssFragment);
  fragment.addEventListener('load', this.step_func((e) => {
    // [verify]
    var fragment1 = fragment.querySelector(selFragment);
    var fragment3 = fragment.querySelector('#fragment3');

    assert_true(fragment3 instanceof HTMLElement);
    assert_true(fragment1 instanceof HTMLElement);
    assert_equals(fragment3.textContent, 'Fragment 3');
    assert_equals(e.detail.fragment, fragment);

    fragment1.addEventListener('load', this.step_func((e) => {
      var fragment1_ = fragment.querySelector('#fragment1');

      assert_true(fragment1_ instanceof HTMLElement);
      assert_equals(fragment1_.textContent, 'Fragment 1');
      assert_equals(e.detail.fragment, fragment1);

      // [teardown]
      fragment.remove();
      this.done();
    }));
  }));

  // [run]
  document.body.appendChild(fragment);
  componentHandler.upgradeElement(fragment);
}, "Import from src='fixtures/fragment3.html' relative path, nested, default insertion");

/**
 * Do nested import following FIFO event calling
 */
onload_test(function(e) {
  // [setup]
  var fragment = document.createElement('div');
  fragment.setAttribute('src', 'fixtures/fragment4.html');
  fragment.classList.add(cssFragment);
  fragment.addEventListener('load', this.step_func((e) => {
    // [verify]
    var fragment = e.detail.fragment;
    assert_true(fragment.querySelector('[src="nested/fragment5.html"]') instanceof HTMLElement);
    assert_true(fragment.querySelector('[src="nested/fragment6.html"]') instanceof HTMLElement);
    assert_true(fragment.querySelector('[src="nested1/fragment7.html"]') instanceof HTMLElement);
    assert_true(fragment.querySelector('[src="nested1/fragment8.html"]') instanceof HTMLElement);
    assert_true(fragment.querySelector('[src="nested1/fragment9.html"]') instanceof HTMLElement);
    assert_true(fragment.querySelector('[src="nested1/fragment10.html"]') instanceof HTMLElement);

    // [setup]
    fragment.querySelector('[src="nested/fragment5.html"]')
            .addEventListener('load', (e) => {
      var fragment = e.detail.fragment;
      console.log(e.detail.fragment);
      fragment.querySelector('[src="nested1/fragment7.html"]')
              .addEventListener('load', (e) => {
        console.log(e.detail.fragment);
      });
      fragment.querySelector('[src="nested1/fragment8.html"]')
              .addEventListener('load', (e) => {
        console.log(e.detail.fragment);
      });
    });
    fragment.querySelector('[src="nested/fragment6.html"]')
            .addEventListener('load', (e) => {
      var fragment = e.detail.fragment;
      console.log(e.detail.fragment);
      fragment.querySelector('[src="nested1/fragment9.html"]')
              .addEventListener('load', (e) => {
        console.log(e.detail.fragment);
      });
      fragment.querySelector('[src="nested1/fragment10.html"]')
              .addEventListener('load', (e) => {
        console.log(e.detail.fragment);
      });
    });

    // [teardown]
    fragment.remove();
    this.done();
  }));

  // [run]
  document.body.appendChild(fragment);
  componentHandler.upgradeElement(fragment);

}, "Import from src='fixtures/fragment4.html' relative path, nested directory, default insertion");

})();
<commit_msg>[TEST] Finish FIFO event loading<commit_after>'use strict';

const classAsString = 'MaterialFragment';
const cssFragment = 'mdl-fragment';
const selFragment = `.${cssFragment}`;

(() => {
/**
 * Do not move this test to any other place and
 * from the index.html
 */
onload_test(function(e) {
  var fragment = document.querySelector(selFragment);

  assert_true(fragment.dataset.upgraded.includes(classAsString));
  this.done();
}, "MDL upgrades the component from the Body");

/**
 * Do not move this test to any other place and
 * from the index.html
 */
onload_test(function(e) {
  var fragment = document.querySelector(selFragment).MaterialFragment;

  assert_true(fragment instanceof MaterialFragment);

  document.querySelector(selFragment).remove();
  this.done();
}, "Check the API");

/**
 * Do a simple import from absolute path
 */
onload_test(function(e) {
  // [setup]
  var fragment = document.createElement('div');
  fragment.setAttribute('src', '/test/fixtures/fragment1.html');
  fragment.classList.add(cssFragment);
  fragment.addEventListener('load', this.step_func((e) => {
    // [verify]
    var fragment1 = fragment.querySelector('#fragment1');
    assert_true(fragment1 instanceof HTMLElement);
    assert_equals(fragment1.textContent, 'Fragment 1');
    assert_equals(e.detail.fragment, fragment);

    // [teardown]
    fragment.remove();
    this.done();
  }));

  // [run]
  document.body.appendChild(fragment);
  componentHandler.upgradeElement(fragment);
}, "Import from src='/test/fixtures/fragment1.html' absolute path, default insertion");

/**
 * Do a simple import from relative path
 */
onload_test(function(e) {
  // [setup]
  var fragment = document.createElement('div');
  fragment.setAttribute('src', 'fixtures/fragment1.html');
  fragment.classList.add(cssFragment);
  fragment.addEventListener('load', this.step_func(() => {
    // [verify]
    var fragment1 = fragment.querySelector('#fragment1');
    assert_true(fragment1 instanceof HTMLElement);
    assert_equals(fragment1.textContent, 'Fragment 1');

    // [teardown]
    fragment.remove();
    this.done();
  }));

  // [run]
  document.body.appendChild(fragment);
  componentHandler.upgradeElement(fragment);
}, "Import from src='/test/fixtures/fragment1.html' relative path, default insertion");

/**
 * Do a nested import from absolute path
 */
onload_test(function(e) {
  // [setup]
  var fragment = document.createElement('div');
  fragment.setAttribute('src', '/test/fixtures/fragment2.html');
  fragment.classList.add(cssFragment);
  fragment.addEventListener('load', this.step_func((e) => {
    // [verify]
    var fragment1 = fragment.querySelector(selFragment);
    var fragment2 = fragment.querySelector('#fragment2');
    assert_true(fragment2 instanceof HTMLElement);
    assert_true(fragment1 instanceof HTMLElement);
    assert_equals(fragment2.textContent, 'Fragment 2');
    assert_equals(e.detail.fragment, fragment);

    fragment1.addEventListener('load', this.step_func((e) => {
      var fragment1_ = fragment.querySelector('#fragment1');

      assert_true(fragment1_ instanceof HTMLElement);
      assert_equals(fragment1_.textContent, 'Fragment 1');
      assert_equals(e.detail.fragment, fragment1);

      // [teardown]
      fragment.remove();
      this.done();
    }));
  }));

  // [run]
  document.body.appendChild(fragment);
  componentHandler.upgradeElement(fragment);
}, "Import from src='/test/fixtures/fragment2.html' absolute path, nested, default insertion");

/**
 * Do a nested import from relative path
 */
onload_test(function(e) {
  // [setup]
  var fragment = document.createElement('div');
  fragment.setAttribute('src', 'fixtures/fragment3.html');
  fragment.classList.add(cssFragment);
  fragment.addEventListener('load', this.step_func((e) => {
    // [verify]
    var fragment1 = fragment.querySelector(selFragment);
    var fragment3 = fragment.querySelector('#fragment3');

    assert_true(fragment3 instanceof HTMLElement);
    assert_true(fragment1 instanceof HTMLElement);
    assert_equals(fragment3.textContent, 'Fragment 3');
    assert_equals(e.detail.fragment, fragment);

    fragment1.addEventListener('load', this.step_func((e) => {
      var fragment1_ = fragment.querySelector('#fragment1');

      assert_true(fragment1_ instanceof HTMLElement);
      assert_equals(fragment1_.textContent, 'Fragment 1');
      assert_equals(e.detail.fragment, fragment1);

      // [teardown]
      fragment.remove();
      this.done();
    }));
  }));

  // [run]
  document.body.appendChild(fragment);
  componentHandler.upgradeElement(fragment);
}, "Import from src='fixtures/fragment3.html' relative path, nested, default insertion");

/**
 * Do nested import following FIFO event calling
 */
onload_test(function(e) {
  // [setup]
  var fragment = document.createElement('div');
  fragment.setAttribute('src', 'fixtures/fragment4.html');
  fragment.classList.add(cssFragment);
  fragment.addEventListener('load', this.step_func((e) => {
    // [verify]
    var fragment = e.detail.fragment;
    assert_true(fragment.querySelector('[src="nested/fragment5.html"]') instanceof HTMLElement);
    assert_true(fragment.querySelector('[src="nested/fragment6.html"]') instanceof HTMLElement);
    assert_true(fragment.querySelector('[src="nested1/fragment7.html"]') instanceof HTMLElement);
    assert_true(fragment.querySelector('[src="nested1/fragment8.html"]') instanceof HTMLElement);
    assert_true(fragment.querySelector('[src="nested1/fragment9.html"]') instanceof HTMLElement);
    assert_true(fragment.querySelector('[src="nested1/fragment10.html"]') instanceof HTMLElement);

    // [setup]
    fragment.querySelector('[src="nested/fragment5.html"]')
            .addEventListener('load', (e) => {
      var fragment = e.detail.fragment;
      assert_true(fragment.querySelector('[src="nested1/fragment7.html"]') instanceof HTMLElement);
      assert_true(fragment.querySelector('[src="nested1/fragment8.html"]') instanceof HTMLElement);
      fragment.querySelector('[src="nested1/fragment7.html"]')
              .addEventListener('load', (e) => {
        exit();
      });
      fragment.querySelector('[src="nested1/fragment8.html"]')
              .addEventListener('load', (e) => {
        exit();
      });
    });
    fragment.querySelector('[src="nested/fragment6.html"]')
            .addEventListener('load', (e) => {
      var fragment = e.detail.fragment;
      assert_true(fragment.querySelector('[src="nested1/fragment9.html"]') instanceof HTMLElement);
      assert_true(fragment.querySelector('[src="nested1/fragment10.html"]') instanceof HTMLElement);
      fragment.querySelector('[src="nested1/fragment9.html"]')
              .addEventListener('load', (e) => {
        exit();
      });
      fragment.querySelector('[src="nested1/fragment10.html"]')
              .addEventListener('load', (e) => {
        exit();
      });
    });

  }));

  var counterLeafs = 0;
  var exit = this.step_func(() => {
    if (++counterLeafs >= 4) {
      // [teardown]
      fragment.remove();
      this.done();
    }
  });

  // [run]
  document.body.appendChild(fragment);
  componentHandler.upgradeElement(fragment);

}, "Import from src='fixtures/fragment4.html' relative path, nested directory, default insertion");

})();
<|endoftext|>


<commit_before><commit_msg>Fast and useful scaffold for the database, needs to be fixed/reworked.<commit_after><|endoftext|>


<commit_before>import log from '../../../core/src/common/log';

const DB_NAME = 'CFxNES.db';
const DB_VERSION = 1;

const {indexedDB} = window;
let dbPromise;

//=========================================================
// Database
//=========================================================

function doWithDB(callback) {
  if (dbPromise == null) {
    dbPromise = openDB();
  }
  return dbPromise.then(db => {
    return new Promise((resolve, reject) => callback(db, resolve, reject));
  });
}

function openDB() {
  return new Promise((resolve, reject) => {
    log.info(`Opening database ${DB_NAME} (version: ${DB_VERSION})`);
    const request = indexedDB.open(DB_NAME, DB_VERSION);
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
    request.onblocked = () => reject(new Error('Database is blocked and cannot be upgraded'));
    request.onupgradeneeded = event => upgrageDB(request, event.oldVersion, event.newVersion);
  });
}

function upgrageDB(request, oldVersion, newVersion) {
  log.info(`Upgrading database ${DB_NAME} from version ${oldVersion} to ${newVersion}`);
  request.result.createObjectStore('nvram', {keyPath: 'sha1'});
}

function doWithClosedDB(callback) {
  if (dbPromise == null) {
    return Promise.resolve();
  }
  return dbPromise.then(db => {
    log.info(`Closing database ${DB_NAME}`);
    db.close();
    dbPromise = null;
    return new Promise(callback);
  });
}

export function deleteDB() {
  return doWithClosedDB((resolve, reject) => {
    log.info(`Deleting database ${DB_NAME}`);
    const request = indexedDB.deleteDatabase(DB_NAME);
    request.onsuccess = () => resolve();
    request.onerror = () => reject(request.error);
    request.onblocked = () => reject(new Error('Database is blocked and cannot be deleted'));
  });
}

//=========================================================
// NVRAM store
//=========================================================

function getNVRAM(sha1) {
  log.info('Getting NVRAM from DB store');
  return doWithDB((db, resolve, reject) => {
    const transaction = db.transaction('nvram', 'readonly');
    const store = transaction.objectStore('nvram');
    const request = store.get(sha1);
    request.onsuccess = () => {
      const result = request.result;
      resolve((result && result['data']) || null);
    };
    request.onerror = () => reject(request.error);
  });
}

function putNVRAM(sha1, data) {
  log.info('Putting NVRAM to DB store');
  return doWithDB((db, resolve, reject) => {
    const transaction = db.transaction('nvram', 'readwrite');
    const store = transaction.objectStore('nvram');
    const request = store.put({'sha1': sha1, 'data': data});
    request.onsuccess = () => resolve();
    request.onerror = () => reject(request.error);
  });
}

function clearNVRAM() {
  log.info('Clearing NVRAM DB store');
  return doWithDB((db, resolve, reject) => {
    const transaction = db.transaction('nvram', 'readwrite');
    const store = transaction.objectStore('nvram');
    const request = store.clear();
    request.onsuccess = () => resolve();
    request.onerror = () => reject(request.error);
  });
}

export const nvramStore = {get: getNVRAM, put: putNVRAM, clear: clearNVRAM};
<commit_msg>Fix database test for Edge.<commit_after>import log from '../../../core/src/common/log';

const DB_NAME = 'CFxNES.db';
const DB_VERSION = 1;

const {indexedDB} = window;
let dbPromise;

//=========================================================
// Database
//=========================================================

function doWithDB(callback) {
  if (dbPromise == null) {
    dbPromise = openDB();
  }
  return dbPromise.then(db => {
    return new Promise((resolve, reject) => callback(db, resolve, reject));
  });
}

function openDB() {
  return new Promise((resolve, reject) => {
    log.info(`Opening database ${DB_NAME} (version: ${DB_VERSION})`);
    const request = indexedDB.open(DB_NAME, DB_VERSION);
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
    request.onblocked = () => reject(new Error('Database is blocked and cannot be upgraded'));
    request.onupgradeneeded = event => upgrageDB(request, event.oldVersion, event.newVersion);
  });
}

function upgrageDB(request, oldVersion, newVersion) {
  log.info(`Upgrading database ${DB_NAME} from version ${oldVersion} to ${newVersion}`);
  request.result.createObjectStore('nvram', {keyPath: 'sha1'});
}

function doWithClosedDB(callback) {
  if (dbPromise == null) {
    return new Promise(callback);
  }
  return dbPromise.then(db => {
    log.info(`Closing database ${DB_NAME}`);
    db.close();
    dbPromise = null;
    return new Promise(callback);
  });
}

export function deleteDB() {
  return doWithClosedDB((resolve, reject) => {
    log.info(`Deleting database ${DB_NAME}`);
    const request = indexedDB.deleteDatabase(DB_NAME);
    request.onsuccess = () => resolve();
    request.onerror = () => reject(request.error);
    request.onblocked = () => reject(new Error('Database is blocked and cannot be deleted'));
  });
}

//=========================================================
// NVRAM store
//=========================================================

function getNVRAM(sha1) {
  log.info('Getting NVRAM from DB store');
  return doWithDB((db, resolve, reject) => {
    const transaction = db.transaction('nvram', 'readonly');
    const store = transaction.objectStore('nvram');
    const request = store.get(sha1);
    request.onsuccess = () => {
      const result = request.result;
      resolve((result && result['data']) || null);
    };
    request.onerror = () => reject(request.error);
  });
}

function putNVRAM(sha1, data) {
  log.info('Putting NVRAM to DB store');
  return doWithDB((db, resolve, reject) => {
    const transaction = db.transaction('nvram', 'readwrite');
    const store = transaction.objectStore('nvram');
    const request = store.put({'sha1': sha1, 'data': data});
    request.onsuccess = () => resolve();
    request.onerror = () => reject(request.error);
  });
}

function clearNVRAM() {
  log.info('Clearing NVRAM DB store');
  return doWithDB((db, resolve, reject) => {
    const transaction = db.transaction('nvram', 'readwrite');
    const store = transaction.objectStore('nvram');
    const request = store.clear();
    request.onsuccess = () => resolve();
    request.onerror = () => reject(request.error);
  });
}

export const nvramStore = {get: getNVRAM, put: putNVRAM, clear: clearNVRAM};
<|endoftext|>


<commit_before><commit_msg>removed debug message<commit_after><|endoftext|>


<commit_before>var { defineSupportCode } = require('cucumber');

defineSupportCode(function({defineParameterType}) {
  defineParameterType({
    regexp: /should|should not/,
    transformer: transform.shouldToBoolean,
    typeName: 'shouldToBoolean'
  });

  defineParameterType({
    regexp: /[^"]+/,
    transformer: transform.stringToVariableName,
    typeName: 'elementName'
  });

  defineParameterType({
    regexp: / button| checkbox| drop down list| field| link| select| tab|/,
    transformer: transform.elementTypeToVariableName,
    typeName: 'elementType'
  });

  defineParameterType({
    regexp: /[^"]*/,
    typeName: 'captureString'
  });
});

var transform = new Transform();

function Transform() {
  this.shouldToBoolean = function(expectation) {
    return expectation === 'should';
  };

  this.stringToVariableName = function(string) {
    var firstWord, i, len, varName, word, words;

    varName = "";
    string = string.replace('&', 'And');

    words = string.split(' ');
    firstWord = words.shift();
    varName += firstWord.charAt(0).toLowerCase() + firstWord.substring(1);

    words = words.map(function(word) {
      return word.charAt(0).toUpperCase() + word.substring(1);
    });

    for (i = 0; i < words.length; i++) {
      word = words[i];
      varName += word;
    }

    return varName;
  };

  this.elementTypeToVariableName = function(string) {
    string = string.trim();
    if (string === "drop down list") {
      return "Select";
    } else {
      return string.charAt(0).toUpperCase() + string.substring(1);
    }
  };
};

module.exports = Transform;
<commit_msg>Fix Transform errors and deprecation warnings<commit_after>var { defineSupportCode } = require('cucumber');

defineSupportCode(function({defineParameterType}) {
  var transform = new Transform();

  defineParameterType({
    regexp: /should|should not/,
    transformer: transform.shouldToBoolean,
    name: 'shouldToBoolean'
  });

  defineParameterType({
    regexp: /[^"]+/,
    transformer: transform.stringToVariableName,
    name: 'elementName'
  });

  defineParameterType({
    regexp: / button| checkbox| drop down list| field| link| select| tab|/,
    transformer: transform.elementTypeToVariableName,
    name: 'elementType'
  });

  defineParameterType({
    regexp: /[^"]*/,
    name: 'captureString'
  });
});

function Transform() {
  this.shouldToBoolean = function(expectation) {
    return expectation === 'should';
  };

  this.stringToVariableName = function(string) {
    var firstWord, i, len, varName, word, words;

    varName = "";
    string = string.replace('&', 'And');

    words = string.split(' ');
    firstWord = words.shift();
    varName += firstWord.charAt(0).toLowerCase() + firstWord.substring(1);

    words = words.map(function(word) {
      return word.charAt(0).toUpperCase() + word.substring(1);
    });

    for (i = 0; i < words.length; i++) {
      word = words[i];
      varName += word;
    }

    return varName;
  };

  this.elementTypeToVariableName = function(string) {
    string = string.trim();
    if (string === "drop down list") {
      return "Select";
    } else {
      return string.charAt(0).toUpperCase() + string.substring(1);
    }
  };
};

module.exports = Transform;
<|endoftext|>


<commit_before>'use strict';

const merge = require('lodash.merge');
const pick = require('lodash.pick');
const isEmpty = require('lodash.isempty');
const get = require('lodash.get');
const forEach = require('lodash.foreach');
const dayjs = require('dayjs');
const version = require('../../../package').version;
const pathToFolder = require('../pathToFolder');

function generateUniquePageId(baseId, existingIdMap) {
  let newId = baseId;
  while (existingIdMap.has(newId)) {
    newId = newId + '-1';
  }

  return newId;
}

function addTimingsToHAR(harPage, visualMetricsData, timings, cpu) {
  const harPageTimings = harPage.pageTimings;

  const _visualMetrics = (harPage._visualMetrics = {});
  harPage._cpu = cpu;

  // We add the timings both as a hidden field and add
  // in pageTimings so we can easily show them in PerfCascade
  if (visualMetricsData) {
    const DO_NOT_INCLUDE_IN_HAR_TIMINGS = [
      'VisualReadiness',
      'SpeedIndex',
      'PerceptualSpeedIndex',
      'VisualProgress'
    ];

    for (let key of Object.keys(visualMetricsData)) {
      if (DO_NOT_INCLUDE_IN_HAR_TIMINGS.indexOf(key) === -1) {
        harPageTimings['_' + key.charAt(0).toLowerCase() + key.slice(1)] =
          visualMetricsData[key];
        _visualMetrics[key] = visualMetricsData[key];
      } else if (key !== 'VisualProgress') {
        _visualMetrics[key] = visualMetricsData[key];
      }
    }

    // Make the visual progress structure more JSON
    _visualMetrics.VisualProgress = jsonifyVisualProgress(
      visualMetricsData.VisualProgress
    );
  } else if (timings && timings.firstPaint) {
    // only add first paint if we don't have visual metrics
    harPageTimings._firstPaint = timings.firstPaint;
  }
  if (timings && timings.pageTimings) {
    harPageTimings._domInteractiveTime = timings.pageTimings.domInteractiveTime;
    harPageTimings._domContentLoadedTime =
      timings.pageTimings.domContentLoadedTime;
  }
}

function addMetaToHAR(index, harPage, url, options) {
  const _meta = (harPage._meta = {});
  _meta.connectivity = get(options, 'connectivity.profile', 'native');
  _meta.connectivity = get(options, 'connectivity.alias', _meta.connectivity);

  if (options.resultURL) {
    const base = options.resultURL.endsWith('/')
      ? options.resultURL
      : options.resultURL + '/';
    if (options.screenshot) {
      _meta.screenshot = `${base}${pathToFolder(
        url,
        options
      )}screenshots/${index + 1}.${options.screenshotParams.type}`;
    }
    if (options.video) {
      _meta.video = `${base}${pathToFolder(url, options)}video/${index +
        1}.mp4`;
    }
    if (options.chrome && options.chrome.timeline) {
      _meta.timeline = `${base}${pathToFolder(url, options)}trace-${index +
        1}.json.gz`;
    }
  }
}

function jsonifyVisualProgress(visualProgress) {
  // Original data looks like
  //  "0=0%, 1500=81%, 1516=81%, 1533=84%, 1550=84%, 1566=84%, 1600=95%, 1683=95%, 1833=100%"
  const progress = visualProgress.split(',');
  const visualProgressJSON = {};
  forEach(progress, value => {
    const eachMetric = value.split('=');
    visualProgressJSON[eachMetric[0].replace(' ', '')] = Number(
      eachMetric[1].replace('%', '')
    );
  });
  return visualProgressJSON;
}

module.exports = {
  addBrowser: function(har, name, version, comment) {
    merge(har.log, {
      browser: {
        name,
        version,
        comment
      }
    });

    if (!comment) {
      delete har.log.browser.comment;
    }

    return har;
  },

  addCreator: function(har, comment) {
    merge(har.log, {
      creator: {
        name: 'Browsertime',
        version: version,
        comment: comment
      }
    });

    if (!comment) {
      delete har.log.creator.comment;
    }

    return har;
  },

  getFullyLoaded: function(har) {
    const fullyLoaded = [];
    const entries = Array.from(har.log.entries);

    for (let page of har.log.pages) {
      const pageStartDateTime = new Date(page.startedDateTime).getTime();
      const pageId = page.id;
      const url = page._url;

      let pageEntries = Array.from(entries);
      pageEntries = Array.from(
        pageEntries.filter(entry => entry.pageref === pageId)
      );

      let pageEnd = 0;
      for (let entry of pageEntries) {
        let entryEnd =
          new Date(entry.startedDateTime).getTime() +
          entry.time -
          new Date(pageStartDateTime).getTime();
        if (entryEnd > pageEnd) {
          pageEnd = entryEnd;
        }
      }
      fullyLoaded.push({ url, fullyLoaded: Number(pageEnd.toFixed(0)) });
    }
    return fullyLoaded;
  },

  mergeHars: function(hars) {
    if (isEmpty(hars)) {
      return undefined;
    }
    if (hars.length === 1) {
      return hars[0];
    }
    let firstLog = hars[0].log;
    let combinedHar = {
      log: pick(firstLog, ['version', 'creator', 'browser', 'comment'])
    };
    let pagesById = new Map();
    let allEntries = [];

    hars.forEach(har => {
      let pages = har.log.pages;
      let entries = har.log.entries;
      pages.forEach(page => {
        let pageId = page.id;
        if (pagesById.has(pageId)) {
          const oldPageId = pageId;
          pageId = generateUniquePageId(oldPageId, pagesById);
          page.id = pageId;
          entries = entries.map(entry => {
            if (entry.pageref === oldPageId) {
              entry.pageref = pageId;
            }
            return entry;
          });
        }
        pagesById.set(pageId, page);
      });
      allEntries = allEntries.concat(entries);
    });

    combinedHar.log.pages = Array.from(pagesById.values());
    combinedHar.log.entries = allEntries;

    return combinedHar;
  },

  getEmptyHAR(url, browser) {
    return {
      log: {
        version: '1.2',
        creator: {
          name: 'Browsertime',
          version: version,
          comment: ''
        },
        browser: {
          name: browser,
          version: ''
        },
        pages: [
          {
            startedDateTime: dayjs().format(),
            id: 'failing_page',
            title: url,
            pageTimings: {},
            comment: ''
          }
        ],
        entries: [],
        comment: ''
      }
    };
  },
  addExtraFieldsToHar(totalResults, har, options) {
    if (har) {
      let harPageNumber = 0;
      // We test one page
      // Let's do a better fix for this later on
      // right now this fixes https://github.com/sitespeedio/browsertime/issues/754
      if (har.log.pages.length === options.iterations) {
        for (let harPage of har.log.pages) {
          let pageNumber = harPageNumber % totalResults.length;
          const visualMetric =
            totalResults[pageNumber].visualMetrics[harPageNumber];
          const browserScript =
            totalResults[pageNumber].browserScripts[harPageNumber];
          const cpu = totalResults[pageNumber].cpu[harPageNumber];

          addMetaToHAR(
            harPageNumber,
            harPage,
            totalResults[pageNumber].info.url,
            options
          );

          if (browserScript) {
            addTimingsToHAR(harPage, visualMetric, browserScript.timings, cpu);
          }
          harPageNumber++;
        }
      } else {
        const numberOfPages = totalResults.length;
        for (let page = 0; page < numberOfPages; page++) {
          for (let iteration = 0; iteration < options.iterations; iteration++) {
            let harIndex = iteration * totalResults.length;
            harIndex += page;

            const visualMetric = totalResults[page].visualMetrics[iteration];
            const browserScript = totalResults[page].browserScripts[iteration];
            const cpu = totalResults[page].cpu[iteration];

            addMetaToHAR(
              iteration,
              har.log.pages[harIndex],
              totalResults[page].info.url,
              options
            );
            // Only add the metrics if we was able to collect the metrics and have a HAR
            if (browserScript && har.log.pages[harIndex]) {
              addTimingsToHAR(
                har.log.pages[harIndex],
                visualMetric,
                browserScript.timings,
                cpu
              );
            }
          }
        }
      }
    }
  }
};
<commit_msg>Verify that we have a HAR before we try to add meta data. (#937)<commit_after>'use strict';

const merge = require('lodash.merge');
const pick = require('lodash.pick');
const isEmpty = require('lodash.isempty');
const get = require('lodash.get');
const forEach = require('lodash.foreach');
const dayjs = require('dayjs');
const version = require('../../../package').version;
const pathToFolder = require('../pathToFolder');
const log = require('intel').getLogger('browsertime');

function generateUniquePageId(baseId, existingIdMap) {
  let newId = baseId;
  while (existingIdMap.has(newId)) {
    newId = newId + '-1';
  }

  return newId;
}

function addTimingsToHAR(harPage, visualMetricsData, timings, cpu) {
  const harPageTimings = harPage.pageTimings;

  const _visualMetrics = (harPage._visualMetrics = {});
  harPage._cpu = cpu;

  // We add the timings both as a hidden field and add
  // in pageTimings so we can easily show them in PerfCascade
  if (visualMetricsData) {
    const DO_NOT_INCLUDE_IN_HAR_TIMINGS = [
      'VisualReadiness',
      'SpeedIndex',
      'PerceptualSpeedIndex',
      'VisualProgress'
    ];

    for (let key of Object.keys(visualMetricsData)) {
      if (DO_NOT_INCLUDE_IN_HAR_TIMINGS.indexOf(key) === -1) {
        harPageTimings['_' + key.charAt(0).toLowerCase() + key.slice(1)] =
          visualMetricsData[key];
        _visualMetrics[key] = visualMetricsData[key];
      } else if (key !== 'VisualProgress') {
        _visualMetrics[key] = visualMetricsData[key];
      }
    }

    // Make the visual progress structure more JSON
    _visualMetrics.VisualProgress = jsonifyVisualProgress(
      visualMetricsData.VisualProgress
    );
  } else if (timings && timings.firstPaint) {
    // only add first paint if we don't have visual metrics
    harPageTimings._firstPaint = timings.firstPaint;
  }
  if (timings && timings.pageTimings) {
    harPageTimings._domInteractiveTime = timings.pageTimings.domInteractiveTime;
    harPageTimings._domContentLoadedTime =
      timings.pageTimings.domContentLoadedTime;
  }
}

function addMetaToHAR(index, harPage, url, options) {
  const _meta = (harPage._meta = {});
  _meta.connectivity = get(options, 'connectivity.profile', 'native');
  _meta.connectivity = get(options, 'connectivity.alias', _meta.connectivity);

  if (options.resultURL) {
    const base = options.resultURL.endsWith('/')
      ? options.resultURL
      : options.resultURL + '/';
    if (options.screenshot) {
      _meta.screenshot = `${base}${pathToFolder(
        url,
        options
      )}screenshots/${index + 1}.${options.screenshotParams.type}`;
    }
    if (options.video) {
      _meta.video = `${base}${pathToFolder(url, options)}video/${index +
        1}.mp4`;
    }
    if (options.chrome && options.chrome.timeline) {
      _meta.timeline = `${base}${pathToFolder(url, options)}trace-${index +
        1}.json.gz`;
    }
  }
}

function jsonifyVisualProgress(visualProgress) {
  // Original data looks like
  //  "0=0%, 1500=81%, 1516=81%, 1533=84%, 1550=84%, 1566=84%, 1600=95%, 1683=95%, 1833=100%"
  const progress = visualProgress.split(',');
  const visualProgressJSON = {};
  forEach(progress, value => {
    const eachMetric = value.split('=');
    visualProgressJSON[eachMetric[0].replace(' ', '')] = Number(
      eachMetric[1].replace('%', '')
    );
  });
  return visualProgressJSON;
}

module.exports = {
  addBrowser: function(har, name, version, comment) {
    merge(har.log, {
      browser: {
        name,
        version,
        comment
      }
    });

    if (!comment) {
      delete har.log.browser.comment;
    }

    return har;
  },

  addCreator: function(har, comment) {
    merge(har.log, {
      creator: {
        name: 'Browsertime',
        version: version,
        comment: comment
      }
    });

    if (!comment) {
      delete har.log.creator.comment;
    }

    return har;
  },

  getFullyLoaded: function(har) {
    const fullyLoaded = [];
    const entries = Array.from(har.log.entries);

    for (let page of har.log.pages) {
      const pageStartDateTime = new Date(page.startedDateTime).getTime();
      const pageId = page.id;
      const url = page._url;

      let pageEntries = Array.from(entries);
      pageEntries = Array.from(
        pageEntries.filter(entry => entry.pageref === pageId)
      );

      let pageEnd = 0;
      for (let entry of pageEntries) {
        let entryEnd =
          new Date(entry.startedDateTime).getTime() +
          entry.time -
          new Date(pageStartDateTime).getTime();
        if (entryEnd > pageEnd) {
          pageEnd = entryEnd;
        }
      }
      fullyLoaded.push({ url, fullyLoaded: Number(pageEnd.toFixed(0)) });
    }
    return fullyLoaded;
  },

  mergeHars: function(hars) {
    if (isEmpty(hars)) {
      return undefined;
    }
    if (hars.length === 1) {
      return hars[0];
    }
    let firstLog = hars[0].log;
    let combinedHar = {
      log: pick(firstLog, ['version', 'creator', 'browser', 'comment'])
    };
    let pagesById = new Map();
    let allEntries = [];

    hars.forEach(har => {
      let pages = har.log.pages;
      let entries = har.log.entries;
      pages.forEach(page => {
        let pageId = page.id;
        if (pagesById.has(pageId)) {
          const oldPageId = pageId;
          pageId = generateUniquePageId(oldPageId, pagesById);
          page.id = pageId;
          entries = entries.map(entry => {
            if (entry.pageref === oldPageId) {
              entry.pageref = pageId;
            }
            return entry;
          });
        }
        pagesById.set(pageId, page);
      });
      allEntries = allEntries.concat(entries);
    });

    combinedHar.log.pages = Array.from(pagesById.values());
    combinedHar.log.entries = allEntries;

    return combinedHar;
  },

  getEmptyHAR(url, browser) {
    return {
      log: {
        version: '1.2',
        creator: {
          name: 'Browsertime',
          version: version,
          comment: ''
        },
        browser: {
          name: browser,
          version: ''
        },
        pages: [
          {
            startedDateTime: dayjs().format(),
            id: 'failing_page',
            title: url,
            pageTimings: {},
            comment: ''
          }
        ],
        entries: [],
        comment: ''
      }
    };
  },
  addExtraFieldsToHar(totalResults, har, options) {
    if (har) {
      let harPageNumber = 0;
      // We test one page
      // Let's do a better fix for this later on
      // right now this fixes https://github.com/sitespeedio/browsertime/issues/754
      if (har.log.pages.length === options.iterations) {
        for (let harPage of har.log.pages) {
          let pageNumber = harPageNumber % totalResults.length;
          const visualMetric =
            totalResults[pageNumber].visualMetrics[harPageNumber];
          const browserScript =
            totalResults[pageNumber].browserScripts[harPageNumber];
          const cpu = totalResults[pageNumber].cpu[harPageNumber];

          addMetaToHAR(
            harPageNumber,
            harPage,
            totalResults[pageNumber].info.url,
            options
          );

          if (browserScript) {
            addTimingsToHAR(harPage, visualMetric, browserScript.timings, cpu);
          }
          harPageNumber++;
        }
      } else {
        const numberOfPages = totalResults.length;
        for (let page = 0; page < numberOfPages; page++) {
          for (let iteration = 0; iteration < options.iterations; iteration++) {
            let harIndex = iteration * totalResults.length;
            harIndex += page;

            const visualMetric = totalResults[page].visualMetrics[iteration];
            const browserScript = totalResults[page].browserScripts[iteration];
            const cpu = totalResults[page].cpu[iteration];
            const harPage = har.log.pages[harIndex];
            // Only add meta if we have a HAR
            if (harPage) {
              addMetaToHAR(
                iteration,
                harPage,
                totalResults[page].info.url,
                options
              );
            } else {
              log.error(
                'Could not add meta data to the HAR, miss page ' + harIndex
              );
            }
            // Only add the metrics if we was able to collect the metrics and have a HAR
            if (browserScript && harPage) {
              addTimingsToHAR(
                harPage,
                visualMetric,
                browserScript.timings,
                cpu
              );
            }
          }
        }
      }
    }
  }
};
<|endoftext|>


<commit_before><commit_msg>Fix sitemap generation script<commit_after><|endoftext|>


<commit_before><commit_msg>fix(xod-project): fix flatten function (create correct links from terminals)<commit_after><|endoftext|>


<commit_before>/*global Reveal, hljs */
/* handles URL query, initialize Reveal and $.sample */
(function($, undefined){
  "use strict";

  // Find slide id
  var slideId = location.search.replace('?',''),
      $targetSlide,
      $targetSlideParent;

  if(slideId && $('section#'+slideId)){
    $targetSlide = $('section#'+slideId);
    $targetSlideParent = $targetSlide.parent();
    slideId = $.inArray($targetSlide.get(0), $targetSlideParent.children());

    // vertical slide
    if($targetSlideParent.is('section')){
      location.hash = '#/' + $.inArray($targetSlideParent.get(0),
                                       $targetSlideParent.parent().children()) + '/' + slideId;
    }else{ // normal horizontal slide
      location.hash = '#/' + slideId;
    }

    location.search = ''; // clear search
  }

  // initialize Reveal
  Reveal.initialize({
    // Display controls in the bottom right corner
    controls: true,

    // Display a presentation progress bar
    progress: true,

    // If true; each slide will be pushed to the browser history
    history: true,

    // Flags if mouse wheel navigation should be enabled
    mouseWheel: true,

    // Apply a 3D roll to links on hover
    rollingLinks: true,

    // UI style
    theme: 'default', // default/neon

    // Transition style
    transition: 'default', // default/cube/page/concave/linear(2d)

    update: function(indexh, indexv){
      // update sample code so that 'height' of iframe is correct
      $('section.present').not('.stack').find('script[type="text/x-sample"]').sample('update');
    }
  });

}(jQuery));<commit_msg>remove sample.js dependency<commit_after>/*global Reveal, hljs */
/* handles URL query, initialize Reveal and $.sample */
(function($, undefined){
  "use strict";

  // Find slide id
  var slideId = location.search.replace('?',''),
      $targetSlide,
      $targetSlideParent;

  if(slideId && $('section#'+slideId)){
    $targetSlide = $('section#'+slideId);
    $targetSlideParent = $targetSlide.parent();
    slideId = $.inArray($targetSlide.get(0), $targetSlideParent.children());

    // vertical slide
    if($targetSlideParent.is('section')){
      location.hash = '#/' + $.inArray($targetSlideParent.get(0),
                                       $targetSlideParent.parent().children()) + '/' + slideId;
    }else{ // normal horizontal slide
      location.hash = '#/' + slideId;
    }

    location.search = ''; // clear search
  }

  // initialize Reveal
  Reveal.initialize({
    // Display controls in the bottom right corner
    controls: true,

    // Display a presentation progress bar
    progress: true,

    // If true; each slide will be pushed to the browser history
    history: true,

    // Flags if mouse wheel navigation should be enabled
    mouseWheel: true,

    // Apply a 3D roll to links on hover
    rollingLinks: true,

    // UI style
    theme: 'default', // default/neon

    // Transition style
    transition: 'default' // default/cube/page/concave/linear(2d)
  });

}(jQuery));<|endoftext|>