<commit_before>var fs = require("fs"),
	express = require("express"),
	app = express(),
	marked = require("marked"),
	mustache = require("mustache"),
	template = fs.readFileSync("./themes/basic/main.html", { "encoding": "utf-8" }),
	archives,
	drafts,
	get_config = function () {
		var config;
		try {
			config = fs.readFileSync("config.json", { "encoding": "utf-8" });
		} catch (e) {
			console.log("ERROR", "Could not find `config.json`. Please run `setup.js`.")
		}
		return config ? JSON.parse(config) : {};
	},
	get_context = function () {
		var context;
		try {
			context = fs.readFileSync("context.json", { "encoding": "utf-8" });
		} catch (e) {
			console.log("ERROR", "Could not find `context.json`. Please run `setup.js`.")
		}
		return context ? JSON.parse(context) : {};
	},
	tripled_variables = ["css", "content", "profile_image"],
	config = get_config(),
	context = get_context();

// By inserting a space in each triplet of braces, this prevents an error with the CSS and Mustache template.
template = template.replace(/\}\}\}/g, "}} }");

// Because Scriptogram only ever uses double-braced variables, replace these with triple-braced.
tripled_variables.forEach(function (v, i, a) {
	template = template.replace(new RegExp("\{\{(" + v + ")\}\}", "g"), "{{{$1}}}");
});

app.use("/themes", express.static('themes'));

app.use(function (req, res, next) {

	var archive_location = config.archives || "";

	fs.readdir("../content/archives/", function (err, files) {
		if (err) {
			res.sendStatus(500); // equivalent to res.status(500).send('Internal Server Error')
		} else {
			archives = files.filter(function (e, i, a) {
				return (e.match(/^\d{12}/));
			});
			context = get_context();
			archives.forEach(function(v, i, a) {
				var current_post = {},
					post_file = "",
					tags_file = "",
					post_title = "";

				try {
					post_file = fs.readFileSync(archive_location + v  + "/" + v + ".md", { "encoding": "utf-8" }),
					tags_file = fs.readFileSync(archive_location + v  + "/" + "tags.txt", { "encoding": "utf-8" });
				} catch (e) {
					console.log("Could not find `" + v + ".md`. May be an issue with the `archives` property in `config.json`.")
				}

				post_title = post_file.match(/^[\s\n\r\t]*\#[\s\t]*([^\n]*)\n*/) || "";
				current_post["title"] =  post_title[1] || "";
				current_post["content"] = marked(post_title[0] ? post_file.replace(post_title[0], "") : "");

				current_post["tags"] = [{ "name": "test" }];

				if (context.hasOwnProperty("posts")) {
					context.posts.push(current_post);
				}

			});

			// TODO: sort out synchronicity
			next();
		}
	});
});

app.use("/draft", function (req, res, next) {
	fs.readdir(config.drafts || "", function (err, files) {
		if (err) {
			res.sendStatus(500); // equivalent to res.status(500).send('Internal Server Error')
		} else {
			drafts = files.filter(function (e, i, a) {
				return true;
			});
			next();
		}
	});
});

app.get("/", function (req, res, next) {
	res.writeHead(200, "text/html");
	res.write(JSON.stringify(archives, null, "\t"));
	next();
});

app.use("/preview", function (req, res, next) {
	res.writeHead(200, "text/html");
	res.write(mustache.render(template, context));
	next();
});

app.get("/draft", function (req, res, next) {
	res.writeHead(200, "text/html");
	res.write(JSON.stringify(archives, null, "\t"));
	res.write(JSON.stringify(drafts, null, "\t") || " ");
	next();
});

app.use(function (req, res, next) {
	res.end();
});

app.listen(1337);<commit_msg>Added line to allow test tags to show.<commit_after>var fs = require("fs"),
	express = require("express"),
	app = express(),
	marked = require("marked"),
	mustache = require("mustache"),
	template = fs.readFileSync("./themes/basic/main.html", { "encoding": "utf-8" }),
	archives,
	drafts,
	get_config = function () {
		var config;
		try {
			config = fs.readFileSync("config.json", { "encoding": "utf-8" });
		} catch (e) {
			console.log("ERROR", "Could not find `config.json`. Please run `setup.js`.")
		}
		return config ? JSON.parse(config) : {};
	},
	get_context = function () {
		var context;
		try {
			context = fs.readFileSync("context.json", { "encoding": "utf-8" });
		} catch (e) {
			console.log("ERROR", "Could not find `context.json`. Please run `setup.js`.")
		}
		return context ? JSON.parse(context) : {};
	},
	tripled_variables = ["css", "content", "profile_image"],
	config = get_config(),
	context = get_context();

// By inserting a space in each triplet of braces, this prevents an error with the CSS and Mustache template.
template = template.replace(/\}\}\}/g, "}} }");

// Because Scriptogram only ever uses double-braced variables, replace these with triple-braced.
tripled_variables.forEach(function (v, i, a) {
	template = template.replace(new RegExp("\{\{(" + v + ")\}\}", "g"), "{{{$1}}}");
});

app.use("/themes", express.static('themes'));

app.use(function (req, res, next) {

	var archive_location = config.archives || "";

	fs.readdir("../content/archives/", function (err, files) {
		if (err) {
			res.sendStatus(500); // equivalent to res.status(500).send('Internal Server Error')
		} else {
			archives = files.filter(function (e, i, a) {
				return (e.match(/^\d{12}/));
			});
			context = get_context();
			archives.forEach(function(v, i, a) {
				var current_post = {},
					post_file = "",
					tags_file = "",
					post_title = "";

				try {
					post_file = fs.readFileSync(archive_location + v  + "/" + v + ".md", { "encoding": "utf-8" }),
					tags_file = fs.readFileSync(archive_location + v  + "/" + "tags.txt", { "encoding": "utf-8" });
				} catch (e) {
					console.log("Could not find `" + v + ".md`. May be an issue with the `archives` property in `config.json`.")
				}

				post_title = post_file.match(/^[\s\n\r\t]*\#[\s\t]*([^\n]*)\n*/) || "";
				current_post["title"] =  post_title[1] || "";
				current_post["content"] = marked(post_title[0] ? post_file.replace(post_title[0], "") : "");

				current_post["if_tags"] = true;
				current_post["tags"] = [{ "name": "test" }];

				if (context.hasOwnProperty("posts")) {
					context.posts.push(current_post);
				}

			});

			// TODO: sort out synchronicity
			next();
		}
	});
});

app.use("/draft", function (req, res, next) {
	fs.readdir(config.drafts || "", function (err, files) {
		if (err) {
			res.sendStatus(500); // equivalent to res.status(500).send('Internal Server Error')
		} else {
			drafts = files.filter(function (e, i, a) {
				return true;
			});
			next();
		}
	});
});

app.get("/", function (req, res, next) {
	res.writeHead(200, "text/html");
	res.write(JSON.stringify(archives, null, "\t"));
	next();
});

app.use("/preview", function (req, res, next) {
	res.writeHead(200, "text/html");
	res.write(mustache.render(template, context));
	next();
});

app.get("/draft", function (req, res, next) {
	res.writeHead(200, "text/html");
	res.write(JSON.stringify(archives, null, "\t"));
	res.write(JSON.stringify(drafts, null, "\t") || " ");
	next();
});

app.use(function (req, res, next) {
	res.end();
});

app.listen(1337);<|endoftext|>


<commit_before>var async = require('async');
var should = require('should');
var config = require('./config.js')
var server = require('./simpleServer.js');
var utils = require('./utils.js');

var serversToShutDown = [];

var HOST = config.rushServer.hostname;
var PORT = config.rushServer.port;

function executeTest(method, content, persistence, done) {
  'use strict';

  var id, options = {};
  options.host = HOST;
  options.port = PORT;
  options.headers = {};
  options.method = method;
  options.headers['content-type'] = 'application/json';
  options.headers['X-Relayer-Host'] = 'http://localhost:8014';
  options.headers['X-relayer-persistence'] = persistence;
  options.headers['test-header'] = 'test header';

  var simpleServer = server.serverListener(

      function() {
        utils.makeRequest(options, content, function(err, res) {
          id = JSON.parse(res).id;
        });
      },

      function(method, headers, body) {

        var checked = false;
        var interval = setInterval(function() {

          var options = { port: PORT, host: HOST,
            path: '/response/' + id, method: 'GET'};

          function checkResponse(err, data, res) {

            if (res.statusCode !== 404 && ! checked) {

              clearInterval(interval);

              var JSONres = JSON.parse(data);

              if (persistence === 'BODY') {

                JSONres.should.have.property('body');
                JSONres.body.should.be.equal(content);
                JSONres.headers.should.have.property('test-header',
                    'test header');
                JSONres.should.have.property('statusCode', '200');

              } else if (persistence === 'HEADER') {

                JSONres.should.not.have.property('body');
                JSONres.should.have.property('headers');
                JSONres.headers.should.have.property('test-header',
                    'test header');
                JSONres.should.have.property('statusCode', '200');

              } else if (persistence === 'STATUS') {

                JSONres.should.not.have.property('body');
                JSONres.should.not.have.property('headers');
                JSONres.should.have.property('statusCode', '200');

              }

              checked = true;
              done();

            }
          }

          utils.makeRequest(options, '', checkResponse);

        }, 10);
      }
  );

  serversToShutDown.push(simpleServer);
}

describe('Feature: Persistence', function() {

  afterEach(function() {
    for (var i = 0; i < serversToShutDown.length; i++) {
      try {
        serversToShutDown[i].close();
      } catch (e) {

      }
    }

    serversToShutDown = [];
  });

  it('should return 404 if the persistence doesn\'t exist', function(done){
    var id = 'not_an_id';
    utils.makeRequest({host:HOST, port:PORT, path : '/response/' + id}, function(err, data, res) {
      should.not.exist(err);
      res.should.have.property('statusCode', 404);
      var JSONres = JSON.parse(data);
      JSONres.should.have.property('error', 'ID ' + id + ' does not exist');
      done();
    });
  });

  it('should return empty body and test-header', function(done) {
    executeTest('GET', '', 'BODY', done);
  });

  it('should return the same body', function(done) {
    executeTest('POST', 'Body Example', 'BODY', done);
  });

  it ('should return status and header. should not return body', function(done) {
    executeTest('POST', 'Body Example', 'HEADER', done);
  });

  it ('should not return body neither heraders', function(done) {
    executeTest('POST', 'Body Example', 'STATUS', done);
  });

  it('should return error headers (ENOTFOUND)', function(done) {
    var id, options = {};
    options.host = HOST;
    options.port = PORT;
    options.headers = {};
    options.method = 'POST';
    options.headers['X-Relayer-Host'] = 'http://notAServer:8014';
    options.headers['X-relayer-persistence'] = 'BODY';
    options.headers['test-header'] = 'test header';

    async.series([
      function(callback) {
        utils.makeRequest(options, 'body request', function(err, res) {
          id = JSON.parse(res).id;

          if (!err) {
            callback(null, res);
          } else {
            callback(err, null);
          }

        });
      },

      function(callback) {

        var checked = false;
        var interval = setInterval(function() {

          var options = { port: PORT, host: HOST,
            path: '/response/' + id, method: 'GET'};

          function checkResponse(err, data, res) {

            if (res.statusCode !== 404 && ! checked) {

              clearInterval(interval);

              if (!err) {
                callback(null, JSON.parse(data));
              } else {
                callback(err, null);
              }

              checked = true;
            }
          }

          utils.makeRequest(options, '', checkResponse);

        }, 10);
      }
    ], function(err, res) {
      var resGet = res[1];
      resGet.should.have.property('error', 'getaddrinfo ENOTFOUND');
      done();
    });
  });
});
<commit_msg>empy body (GET method)<commit_after>var async = require('async');
var should = require('should');
var config = require('./config.js')
var server = require('./simpleServer.js');
var utils = require('./utils.js');

var serversToShutDown = [];

var HOST = config.rushServer.hostname;
var PORT = config.rushServer.port;

function executeTest(method, content, persistence, done) {
  'use strict';

  var id, options = {};
  options.host = HOST;
  options.port = PORT;
  options.headers = {};
  options.method = method;
  options.headers['content-type'] = 'application/json';
  options.headers['X-Relayer-Host'] = 'http://localhost:8014';
  options.headers['X-relayer-persistence'] = persistence;
  options.headers['test-header'] = 'test header';

  var simpleServer = server.serverListener(

      function() {
        utils.makeRequest(options, content, function(err, res) {
          id = JSON.parse(res).id;
        });
      },

      function(method, headers, body) {

        var checked = false;
        var interval = setInterval(function() {

          var options = { port: PORT, host: HOST,
            path: '/response/' + id, method: 'GET'};

          function checkResponse(err, data, res) {

            if (res.statusCode !== 404 && ! checked) {

              clearInterval(interval);

              var JSONres = JSON.parse(data);

              if (persistence === 'BODY') {

                JSONres.should.have.property('body');
                JSONres.body.should.be.equal(content);
                JSONres.headers.should.have.property('test-header',
                    'test header');
                JSONres.should.have.property('statusCode', '200');

              } else if (persistence === 'HEADER') {

                JSONres.should.not.have.property('body');
                JSONres.should.have.property('headers');
                JSONres.headers.should.have.property('test-header',
                    'test header');
                JSONres.should.have.property('statusCode', '200');

              } else if (persistence === 'STATUS') {

                JSONres.should.not.have.property('body');
                JSONres.should.not.have.property('headers');
                JSONres.should.have.property('statusCode', '200');

              }

              checked = true;
              done();

            }
          }

          utils.makeRequest(options, '', checkResponse);

        }, 10);
      }
  );

  serversToShutDown.push(simpleServer);
}

describe('Feature: Persistence', function() {

  afterEach(function() {
    for (var i = 0; i < serversToShutDown.length; i++) {
      try {
        serversToShutDown[i].close();
      } catch (e) {

      }
    }

    serversToShutDown = [];
  });

  it('should return 404 if the persistence doesn\'t exist', function(done){
    var id = 'not_an_id';
    utils.makeRequest({host:HOST, port:PORT, path : '/response/' + id}, '', function(err, data, res) {
      should.not.exist(err);
      res.should.have.property('statusCode', 404);
      var JSONres = JSON.parse(data);
      JSONres.should.have.property('error', 'ID ' + id + ' does not exist');
      done();
    });
  });

  it('should return empty body and test-header', function(done) {
    executeTest('GET', '', 'BODY', done);
  });

  it('should return the same body', function(done) {
    executeTest('POST', 'Body Example', 'BODY', done);
  });

  it ('should return status and header. should not return body', function(done) {
    executeTest('POST', 'Body Example', 'HEADER', done);
  });

  it ('should not return body neither heraders', function(done) {
    executeTest('POST', 'Body Example', 'STATUS', done);
  });

  it('should return error headers (ENOTFOUND)', function(done) {
    var id, options = {};
    options.host = HOST;
    options.port = PORT;
    options.headers = {};
    options.method = 'POST';
    options.headers['X-Relayer-Host'] = 'http://notAServer:8014';
    options.headers['X-relayer-persistence'] = 'BODY';
    options.headers['test-header'] = 'test header';

    async.series([
      function(callback) {
        utils.makeRequest(options, 'body request', function(err, res) {
          id = JSON.parse(res).id;

          if (!err) {
            callback(null, res);
          } else {
            callback(err, null);
          }

        });
      },

      function(callback) {

        var checked = false;
        var interval = setInterval(function() {

          var options = { port: PORT, host: HOST,
            path: '/response/' + id, method: 'GET'};

          function checkResponse(err, data, res) {

            if (res.statusCode !== 404 && ! checked) {

              clearInterval(interval);

              if (!err) {
                callback(null, JSON.parse(data));
              } else {
                callback(err, null);
              }

              checked = true;
            }
          }

          utils.makeRequest(options, '', checkResponse);

        }, 10);
      }
    ], function(err, res) {
      var resGet = res[1];
      resGet.should.have.property('error', 'getaddrinfo ENOTFOUND');
      done();
    });
  });
});
<|endoftext|>


<commit_before>/* global browser, describe, it */
/* jshint node: true */

var should = require('should'); // jshint ignore:line
var url = require('url');

describe('Test basic API commands for YouTube tech', function() {
  // YouTube sometime hate us and sometime love us (pretty random)
  // We can't rely on this test to know if it really crash so we ignore his feeling
  /*it('should play and pause', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").play()');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").paused()').then(function(paused) {
      paused.should.be.false;
    });

    browser.driver.executeScript('videojs("vid1").pause();');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").paused()').then(function(paused) {
      paused.should.be.true;
    });
  });*/

  it('should change the source with regular URL', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").src("https://www.youtube.com/watch?v=y6Sxv-sUYtM");');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").src()').then(function(src) {
      src.should.equal('https://www.youtube.com/watch?v=y6Sxv-sUYtM');
    });
  });

  it('should change the source with Youtu.be URL', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").src("https://www.youtu.be/watch?v=y6Sxv-sUYtM");');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").src()').then(function(src) {
      src.should.equal('https://www.youtu.be/watch?v=y6Sxv-sUYtM');
    });
  });

  it('should change the source with Embeded URL', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").src("https://www.youtube.com/embed/y6Sxv-sUYtM");');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").src()').then(function(src) {
      src.should.equal('https://www.youtube.com/embed/y6Sxv-sUYtM');
    });
  });

  it('should change the source with playlist URL', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript(
      'videojs("vid1").src("http://www.youtube.com/watch?v=xjS6SftYQaQ&list=SPA60DCEB33156E51F");');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").src()').then(function(src) {
      src.should.equal('http://www.youtube.com/watch?v=xjS6SftYQaQ&list=SPA60DCEB33156E51F');
    });
  });

  // YouTube doesn't seek it until it is ready and we can't know the loading delay
  /*it('should seek at a specific time', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").currentTime(10);');

    browser.driver.executeScript('return videojs("vid1").currentTime()').then(function(currentTime) {
      currentTime.should.equal(10);
    });
  });*/

  it('should know duration', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").play()');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").duration()').then(function(duration) {
      duration.should.be.within(227, 228);
    });
  });

  it('should set the volume, mute and unmute', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").play()');
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").volume(0.5)');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").volume()').then(function(volume) {
      volume.should.equal(0.5);
    });

    browser.driver.executeScript('return videojs("vid1").muted()').then(function(muted) {
      muted.should.be.false; // jshint ignore:line
    });

    browser.driver.executeScript('videojs("vid1").play();videojs("vid1").muted(true);');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").muted()').then(function(muted) {
      muted.should.be.true; // jshint ignore:line
    });

    browser.driver.executeScript('videojs("vid1").play();videojs("vid1").muted(false);');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").muted()').then(function(muted) {
      muted.should.be.false; // jshint ignore:line
    });
  });

  it('should switch technologies', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);
    browser.driver.executeScript('videojs("vid1").play()');

    browser.driver.executeScript('videojs("vid1").src({ src: "http://vjs.zencdn.net/v/oceans.mp4", ' +
      'type: "video/mp4" });');
    browser.driver.sleep(1000);

    browser.driver.executeScript('videojs("vid1").play()');
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").src({src:"https://www.youtu.be/watch?v=y6Sxv-sUYtM", ' +
      'type: "video/youtube" });');
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").play()');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").src()').then(function(src) {
      src.should.equal('https://www.youtu.be/watch?v=y6Sxv-sUYtM');
    });
  });
});
<commit_msg>Removed the functional tests (too unpredicble, let's write a YouTube API mock instead)<commit_after>/* global browser, describe, it */
/* jshint node: true */

// TODO: Write a YouTube API mock to test without loading the real video, the result is too unpredictable
/*var should = require('should'); // jshint ignore:line
var url = require('url');

describe('Test basic API commands for YouTube tech', function() {
  // YouTube sometime hate us and sometime love us (pretty random)
  // We can't rely on this test to know if it really crash so we ignore his feeling
  it('should play and pause', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").play()');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").paused()').then(function(paused) {
      paused.should.be.false;
    });

    browser.driver.executeScript('videojs("vid1").pause();');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").paused()').then(function(paused) {
      paused.should.be.true;
    });
  });

  it('should change the source with regular URL', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").src("https://www.youtube.com/watch?v=y6Sxv-sUYtM");');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").src()').then(function(src) {
      src.should.equal('https://www.youtube.com/watch?v=y6Sxv-sUYtM');
    });
  });

  it('should change the source with Youtu.be URL', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").src("https://www.youtu.be/watch?v=y6Sxv-sUYtM");');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").src()').then(function(src) {
      src.should.equal('https://www.youtu.be/watch?v=y6Sxv-sUYtM');
    });
  });

  it('should change the source with Embeded URL', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").src("https://www.youtube.com/embed/y6Sxv-sUYtM");');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").src()').then(function(src) {
      src.should.equal('https://www.youtube.com/embed/y6Sxv-sUYtM');
    });
  });

  it('should change the source with playlist URL', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript(
      'videojs("vid1").src("http://www.youtube.com/watch?v=xjS6SftYQaQ&list=SPA60DCEB33156E51F");');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").src()').then(function(src) {
      src.should.equal('http://www.youtube.com/watch?v=xjS6SftYQaQ&list=SPA60DCEB33156E51F');
    });
  });

  it('should seek at a specific time', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").currentTime(10);');

    browser.driver.executeScript('return videojs("vid1").currentTime()').then(function(currentTime) {
      currentTime.should.equal(10);
    });
  });

  it('should know duration', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").play()');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").duration()').then(function(duration) {
      duration.should.be.within(227, 228);
    });
  });

  it('should set the volume, mute and unmute', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").play()');
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").volume(0.5)');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").volume()').then(function(volume) {
      volume.should.equal(0.5);
    });

    browser.driver.executeScript('return videojs("vid1").muted()').then(function(muted) {
      muted.should.be.false; // jshint ignore:line
    });

    browser.driver.executeScript('videojs("vid1").play();videojs("vid1").muted(true);');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").muted()').then(function(muted) {
      muted.should.be.true; // jshint ignore:line
    });

    browser.driver.executeScript('videojs("vid1").play();videojs("vid1").muted(false);');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").muted()').then(function(muted) {
      muted.should.be.false; // jshint ignore:line
    });
  });

  it('should switch technologies', function() {
    browser.driver.get(url.resolve(browser.baseUrl, '/sandbox/index.html'));
    browser.driver.sleep(5000);
    browser.driver.executeScript('videojs("vid1").play()');

    browser.driver.executeScript('videojs("vid1").src({ src: "http://vjs.zencdn.net/v/oceans.mp4", ' +
      'type: "video/mp4" });');
    browser.driver.sleep(1000);

    browser.driver.executeScript('videojs("vid1").play()');
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").src({src:"https://www.youtu.be/watch?v=y6Sxv-sUYtM", ' +
      'type: "video/youtube" });');
    browser.driver.sleep(5000);

    browser.driver.executeScript('videojs("vid1").play()');
    browser.driver.sleep(5000);

    browser.driver.executeScript('return videojs("vid1").src()').then(function(src) {
      src.should.equal('https://www.youtu.be/watch?v=y6Sxv-sUYtM');
    });
  });
});
*/
<|endoftext|>


<commit_before>'use strict';

describe('pipeline', function () {
  it('should return correct result', function (done) {
    var redis = new Redis();
    redis.pipeline().set('foo', '1').get('foo').set('foo', '2').incr('foo').get('foo').exec(function (err, results) {
      expect(err).to.eql(null);
      expect(results).to.eql([
        [null, 'OK'],
        [null, '1'],
        [null, 'OK'],
        [null, 3],
        [null, '3']
      ]);
      done();
    });
  });

  it('should return an empty array on empty pipeline', function(done) {
    var redis = new Redis();
    redis.pipeline().exec(function(err, results) {
      expect(err).to.eql(null);
      expect(results).to.eql([]);
      done();
    });
  });

  it('should support mix string command and buffer command', function (done) {
    var redis = new Redis();
    redis.pipeline().set('foo', 'bar').set('foo', new Buffer('bar')).getBuffer('foo').get(new Buffer('foo')).exec(function (err, results) {
      expect(err).to.eql(null);
      expect(results).to.eql([
        [null, 'OK'],
        [null, 'OK'],
        [null, new Buffer('bar')],
        [null, 'bar']
      ]);
      done();
    });
  });

  it('should handle error correctly', function (done) {
    var redis = new Redis();
    redis.pipeline().set('foo').exec(function (err, results) {
      expect(err).to.eql(null);
      expect(results.length).to.eql(1);
      expect(results[0].length).to.eql(1);
      expect(results[0][0].toString()).to.match(/wrong number of arguments/);
      done();
    });
  });

  it('should also invoke the command\'s callback', function (done) {
    var redis = new Redis();
    var pending = 1;
    redis.pipeline().set('foo', 'bar').get('foo', function (err, result) {
      expect(result).to.eql('bar');
      pending -= 1;
    }).exec(function (err, results) {
      expect(pending).to.eql(0);
      expect(results[1][1]).to.eql('bar');
      done();
    });
  });

  it('should support inline transaction', function (done) {
    var redis = new Redis();

    redis.pipeline().multi().set('foo', 'bar').get('foo').exec().exec(function (err, result) {
      expect(result[0][1]).to.eql('OK');
      expect(result[1][1]).to.eql('QUEUED');
      expect(result[2][1]).to.eql('QUEUED');
      expect(result[3][1]).to.eql(['OK', 'bar']);
      done();
    });
  });

  it('should have the same options as its container', function () {
    var redis = new Redis({ showFriendlyErrorStack: true });
    var pipeline = redis.pipeline();
    expect(pipeline.options).to.have.property('showFriendlyErrorStack', true);
  });

  it('should support key prefixing', function (done) {
    var redis = new Redis({ keyPrefix: 'foo:' });
    redis.pipeline().set('bar', 'baz').get('bar').lpush('app1', 'test1').lpop('app1').keys('*').exec(function (err, results) {
      expect(err).to.eql(null);
      expect(results).to.eql([
        [null, 'OK'],
        [null, 'baz'],
        [null, 1],
        [null, 'test1'],
        [null, ['foo:bar']]
      ]);
      done();
    });
  });

  describe('custom commands', function() {
    var redis;

    before(function() {
      redis = new Redis();
      redis.defineCommand('echo', {
        numberOfKeys: 2,
        lua: 'return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}'
      });
    });

    it('should work', function(done) {
      redis.pipeline().echo('foo', 'bar', '123', 'abc').exec(function(err, results) {
        expect(err).to.eql(null);
        expect(results).to.eql([
          [null, ['foo', 'bar', '123', 'abc']]
        ]);
        done();
      });
    });

    it('should support callbacks', function(done) {
      var pending = 1;
      redis.pipeline()
        .echo('foo', 'bar', '123', 'abc', function(err, result) {
          pending -= 1;
          expect(err).to.eql(null);
          expect(result).to.eql(['foo', 'bar', '123', 'abc']);
        })
        .exec(function(err, results) {
          expect(err).to.eql(null);
          expect(results).to.eql([
            [null, ['foo', 'bar', '123', 'abc']]
          ]);
          expect(pending).to.eql(0);
          done();
        });
    });

    it('should be supported in transaction blocks', function(done) {
      redis.pipeline()
        .multi()
        .set('foo', 'asdf')
        .echo('bar', 'baz', '123', 'abc')
        .get('foo')
        .exec()
        .exec(function(err, results) {
          expect(err).to.eql(null);
          expect(results[4][1][1]).to.eql(['bar', 'baz', '123', 'abc']);
          expect(results[4][1][2]).to.eql('asdf');
          done();
        });
    });
  });

  describe('#addBatch', function () {
    it('should accept commands in constructor', function (done) {
      var redis = new Redis();
      var pending = 1;
      redis.pipeline([
        ['set', 'foo', 'bar'],
        ['get', 'foo', function (err, result) {
          expect(result).to.eql('bar');
          pending -= 1;
        }]
      ]).exec(function (err, results) {
        expect(pending).to.eql(0);
        expect(results[1][1]).to.eql('bar');
        done();
      });
    });
  });

  describe('exec', function () {
    it('should group results', function (done) {
      var redis = new Redis();
      redis.multi({ pipeline: false });
      redis.set('foo', 'bar');
      redis.get('foo');
      redis.exec().then(function (res) {
        done();
      });
    });

    it('should allow omitting callback', function (done) {
      var redis = new Redis();
      redis.exec().catch(function (err) {
        expect(err.message).to.eql('ERR EXEC without MULTI');
        done();
      });
    });
  });
});
<commit_msg>style: format test code<commit_after>'use strict';

describe('pipeline', function () {
  it('should return correct result', function (done) {
    var redis = new Redis();
    redis.pipeline().set('foo', '1').get('foo').set('foo', '2').incr('foo').get('foo').exec(function (err, results) {
      expect(err).to.eql(null);
      expect(results).to.eql([
        [null, 'OK'],
        [null, '1'],
        [null, 'OK'],
        [null, 3],
        [null, '3']
      ]);
      done();
    });
  });

  it('should return an empty array on empty pipeline', function (done) {
    var redis = new Redis();
    redis.pipeline().exec(function (err, results) {
      expect(err).to.eql(null);
      expect(results).to.eql([]);
      done();
    });
  });

  it('should support mix string command and buffer command', function (done) {
    var redis = new Redis();
    redis.pipeline().set('foo', 'bar')
    .set('foo', new Buffer('bar')).getBuffer('foo')
    .get(new Buffer('foo'))
    .exec(function (err, results) {
      expect(err).to.eql(null);
      expect(results).to.eql([
        [null, 'OK'],
        [null, 'OK'],
        [null, new Buffer('bar')],
        [null, 'bar']
      ]);
      done();
    });
  });

  it('should handle error correctly', function (done) {
    var redis = new Redis();
    redis.pipeline().set('foo').exec(function (err, results) {
      expect(err).to.eql(null);
      expect(results.length).to.eql(1);
      expect(results[0].length).to.eql(1);
      expect(results[0][0].toString()).to.match(/wrong number of arguments/);
      done();
    });
  });

  it('should also invoke the command\'s callback', function (done) {
    var redis = new Redis();
    var pending = 1;
    redis.pipeline().set('foo', 'bar').get('foo', function (err, result) {
      expect(result).to.eql('bar');
      pending -= 1;
    }).exec(function (err, results) {
      expect(pending).to.eql(0);
      expect(results[1][1]).to.eql('bar');
      done();
    });
  });

  it('should support inline transaction', function (done) {
    var redis = new Redis();

    redis.pipeline().multi().set('foo', 'bar').get('foo').exec().exec(function (err, result) {
      expect(result[0][1]).to.eql('OK');
      expect(result[1][1]).to.eql('QUEUED');
      expect(result[2][1]).to.eql('QUEUED');
      expect(result[3][1]).to.eql(['OK', 'bar']);
      done();
    });
  });

  it('should have the same options as its container', function () {
    var redis = new Redis({ showFriendlyErrorStack: true });
    var pipeline = redis.pipeline();
    expect(pipeline.options).to.have.property('showFriendlyErrorStack', true);
  });

  it('should support key prefixing', function (done) {
    var redis = new Redis({ keyPrefix: 'foo:' });
    redis.pipeline().set('bar', 'baz').get('bar').lpush('app1', 'test1')
    .lpop('app1').keys('*').exec(function (err, results) {
      expect(err).to.eql(null);
      expect(results).to.eql([
        [null, 'OK'],
        [null, 'baz'],
        [null, 1],
        [null, 'test1'],
        [null, ['foo:bar']]
      ]);
      done();
    });
  });

  describe('custom commands', function () {
    var redis;

    before(function () {
      redis = new Redis();
      redis.defineCommand('echo', {
        numberOfKeys: 2,
        lua: 'return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}'
      });
    });

    it('should work', function (done) {
      redis.pipeline().echo('foo', 'bar', '123', 'abc').exec(function(err, results) {
        expect(err).to.eql(null);
        expect(results).to.eql([
          [null, ['foo', 'bar', '123', 'abc']]
        ]);
        done();
      });
    });

    it('should support callbacks', function (done) {
      var pending = 1;
      redis.pipeline()
        .echo('foo', 'bar', '123', 'abc', function (err, result) {
          pending -= 1;
          expect(err).to.eql(null);
          expect(result).to.eql(['foo', 'bar', '123', 'abc']);
        })
        .exec(function (err, results) {
          expect(err).to.eql(null);
          expect(results).to.eql([
            [null, ['foo', 'bar', '123', 'abc']]
          ]);
          expect(pending).to.eql(0);
          done();
        });
    });

    it('should be supported in transaction blocks', function (done) {
      redis.pipeline()
        .multi()
        .set('foo', 'asdf')
        .echo('bar', 'baz', '123', 'abc')
        .get('foo')
        .exec()
        .exec(function (err, results) {
          expect(err).to.eql(null);
          expect(results[4][1][1]).to.eql(['bar', 'baz', '123', 'abc']);
          expect(results[4][1][2]).to.eql('asdf');
          done();
        });
    });
  });

  describe('#addBatch', function () {
    it('should accept commands in constructor', function (done) {
      var redis = new Redis();
      var pending = 1;
      redis.pipeline([
        ['set', 'foo', 'bar'],
        ['get', 'foo', function (err, result) {
          expect(result).to.eql('bar');
          pending -= 1;
        }]
      ]).exec(function (err, results) {
        expect(pending).to.eql(0);
        expect(results[1][1]).to.eql('bar');
        done();
      });
    });
  });

  describe('exec', function () {
    it('should group results', function (done) {
      var redis = new Redis();
      redis.multi({ pipeline: false });
      redis.set('foo', 'bar');
      redis.get('foo');
      redis.exec().then(function () {
        done();
      });
    });

    it('should allow omitting callback', function (done) {
      var redis = new Redis();
      redis.exec().catch(function (err) {
        expect(err.message).to.eql('ERR EXEC without MULTI');
        done();
      });
    });
  });
});
<|endoftext|>


<commit_before>/* jshint strict: true, undef: true, unused: true */
/* global describe, it, expect, beforeEach */

require([
    'pastry/pastry'
], function (
    pastry
) {
    'use strict';

    var noop = function () { };

    describe('core->pastry.is$Type(obj)', function () {
        it('pastry.isArguments', function () {
            expect(pastry.isArguments([])).toBe(false);
            expect(pastry.isArguments(arguments)).toBe(true);
        });
        it('pastry.isArray', function () {
            expect(pastry.isArray([])).toBe(true);
            expect(pastry.isArray(1)).toBe(false);
        });
        it('pastry.isBoolean', function () {
            expect(pastry.isBoolean(true)).toBe(true);
            expect(pastry.isBoolean(false)).toBe(true);
            expect(pastry.isBoolean(1)).toBe(false);
        });
        it('pastry.isFunction', function () {
            expect(pastry.isFunction(noop)).toBe(true);
            expect(pastry.isFunction(1)).toBe(false);
        });
        it('pastry.isNumber', function () {
            expect(pastry.isNumber(NaN)).toBe(true);
            expect(pastry.isNumber(1)).toBe(true);
            expect(pastry.isNumber('1')).toBe(false);
        });
        it('pastry.isFinite', function () {
            expect(pastry.isFinite(NaN)).toBe(false);
            expect(pastry.isFinite(1)).toBe(true);
            expect(pastry.isFinite('1')).toBe(false); // 这里和 underscore.js 行为不同
        });
        it('pastry.isObject', function () {
            expect(pastry.isObject({})).toBe(true);
            expect(pastry.isObject(null)).toBe(false);
            expect(pastry.isObject(noop.prototype)).toBe(true);
            expect(pastry.isObject(noop)).toBe(true);
        });
    });

    describe('core->helper functions of arrays', function () {
        var arrA, arrB,
            indexOf = pastry.index(true),
            lastIndexOf = pastry.index(false);

        beforeEach(function () {
            arrA = [1, 2, 3, 3, 4, 4, 4, 5];
            arrB = [];
        });

        it('pastry.indexOf(arr, searchElement, fromIndex)', function () {
            expect(indexOf(arrA, 1)).toBe(0);
            expect(indexOf(arrA, 4)).toBe(4);
            expect(indexOf(arrA, 5)).toBe(7);
            expect(indexOf(arrA, 6)).toBe(-1);
        });

        it('pastry.lastIndexOf(arr, searchElement, fromIndex)', function () {
            expect(lastIndexOf(arrA, 5)).toBe(7);
            expect(lastIndexOf(arrA, 3)).toBe(3);
            expect(lastIndexOf(arrA, 2)).toBe(1);
            expect(lastIndexOf(arrA, 6)).toBe(-1);
        });
        it('pastry.forEach(obj, callback, thisObj)', function () {
            pastry.forEach(arrA, function (a) {
                a += 0;
                arrB.push(a);
            });
            expect(arrB).toEqual([1, 2, 3, 3, 4, 4, 4, 5]);
            arrB = [];
            pastry.forEach(arrA, function (a) {
                a += 1;
                arrB.push(a);
            });
            expect(arrB).toEqual([2, 3, 4, 4, 5, 5, 5, 6]);
        });
        it('pastry.each(obj, callback, thisObj)', function () { // alias
            pastry.each(arrA, function (a) {
                a += 0;
                arrB.push(a);
            });
            expect(arrB).toEqual([1, 2, 3, 3, 4, 4, 4, 5]);
            arrB = [];
            pastry.each(arrA, function (a) {
                a += 1;
                arrB.push(a);
            });
            expect(arrB).toEqual([2, 3, 4, 4, 5, 5, 5, 6]);
        });
        it('pastry.remove(arr, fromIndex, toIndex)', function () {
            pastry.remove(arrA, 0, 2);
            expect(arrA).toEqual([3, 4, 4, 4, 5]);
            pastry.remove(arrA, 0);
            expect(arrA).toEqual([4, 4, 4, 5]);
            pastry.remove(arrA, 0, -1);
            expect(arrA).toEqual([]);
        });
        it('CANNOT use pastry.remove() inside of pastry.each() callback to THE SAME ARRAY', function () {
            pastry.each(arrA, function (num, i) {
                if (num === 4) {
                    pastry.remove(arrA, i);
                }
            });
            // expect(arrA).toEqual([1, 2, 3, 3, 5]); // !!!!!!!!!! REMEMBER THIS !!!!!!!!!!
            // expect(arrA).toEqual([1, 2, 3, 3, 4, 4, 4, 5]);
        });
        var obj = {
            foo: 'bar',
            hoo: 'goo'
        };
        it('delete in pastry.each()', function () {
            pastry.each(obj, function (value, key) {
                if (value === 'bar') {
                    delete obj[key];
                }
            });
            expect(obj).toEqual({
                hoo: 'goo'
            });
            expect(obj.foo).toBe(undefined);
        });
    });

    describe('core->helper functions of functions', function () {
        it('pastry.bind', function () {
            function foo1() {
                return this.hello;
            }

            var bar1 = pastry.bind(foo1, {hello: 'pastry'});
            expect(bar1()).toEqual('pastry');

            function foo2() {
                return arguments[0];
            }

            var bar2 = pastry.bind(foo2, null, 'pastry');
            expect(bar2()).toEqual('pastry');

            function foo3() {
                return arguments[1];
            }

            var bar3 = pastry.bind(foo3, null, 'hello');
            expect(bar3('pastry')).toEqual('pastry');
        });
    });
    describe('core->helper functions of cullections', function () {
        it('pastry.reduce', function () {
            var sum = pastry.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0);
            expect(sum).toBe(6);
        });
    });

    describe('core->helper functions of objects', function () {
        var destObj1 = {},
            destObj2 = {},
            obj1 = {
                hello: 'world'
            },
            obj2 = {
                foo: 'bar',
                bar: {
                    hi: 'hello',
                    woo: 'weee',
                    wee: {
                        hoo: 'gee',
                        hi: 'hi'
                    }
                }
            },
            obj3 = {
                foo: 'too',
                bar: {
                    woo: 'waaa',
                    wee: {
                        hi: 'hoo'
                    }
                },
                hello: [
                    'world',
                    'html',
                    'pastry'
                ]
            };
        pastry.merge(destObj1, obj1, obj2, obj3);
        it('pastry.merge(dest)', function () { // 深度合并
            // expect(destObj1.hello).toBe('world');
            expect(destObj1.foo).toBe('too');
            expect(destObj1.bar.woo).toBe('waaa');
            expect(destObj1.bar.hi).toBe('hello');
            expect(destObj1.bar.wee.hoo).toBe('gee');
            expect(destObj1.bar.wee.hi).toBe('hoo');
            console.log(destObj1.hello);
            expect(destObj1.hello).toEqual(['world', 'html', 'pastry']);
            expect(Object.prototype.toString.call(destObj1.hello)).toBe('[object Array]');
        });
        pastry.extend(destObj2, obj1, obj2, obj3);
        it('pastry.extend(dest)', function () { // 扩展
            expect(destObj1.hello).toEqual(['world', 'html', 'pastry']);
            expect(destObj2.foo).toBe('too');
            expect(destObj2.bar.woo).toBe('waaa');
            expect(destObj2.bar.hi).toBe(undefined);
            expect(destObj2.bar.wee.hoo).toBe(undefined);
            expect(destObj2.bar.wee.hi).toBe('hoo');
        });
    });

    describe('core->others', function () {
        it('pastry.getAny', function () {
            expect(pastry.getAny([
                function () {
                    pastry.ERROR('hi');
                },
                function () {
                    pastry.ERROR('error');
                },
                function () {
                    return 'hello';
                },
            ])).toBe('hello');
        });
    });
});

<commit_msg>add extra test cases for pastry/pastry<commit_after>/* jshint strict: true, undef: true, unused: true */
/* global describe, it, expect, beforeEach */

require([
    'pastry/pastry'
], function (
    pastry
) {
    'use strict';

    var noop = function () { };

    describe('core->pastry.is$Type(obj)', function () {
        it('pastry.isArguments', function () {
            expect(pastry.isArguments([])).toBe(false);
            expect(pastry.isArguments(arguments)).toBe(true);
        });
        it('pastry.isArray', function () {
            expect(pastry.isArray([])).toBe(true);
            expect(pastry.isArray(1)).toBe(false);
        });
        it('pastry.isBoolean', function () {
            expect(pastry.isBoolean(true)).toBe(true);
            expect(pastry.isBoolean(false)).toBe(true);
            expect(pastry.isBoolean(1)).toBe(false);
        });
        it('pastry.isFunction', function () {
            expect(pastry.isFunction(noop)).toBe(true);
            expect(pastry.isFunction(1)).toBe(false);
        });
        it('pastry.isNumber', function () {
            expect(pastry.isNumber(NaN)).toBe(true);
            expect(pastry.isNumber(1)).toBe(true);
            expect(pastry.isNumber('1')).toBe(false);
        });
        it('pastry.isFinite', function () {
            expect(pastry.isFinite(NaN)).toBe(false);
            expect(pastry.isFinite(1)).toBe(true);
            expect(pastry.isFinite('1')).toBe(false); // 这里和 underscore.js 行为不同
        });
        it('pastry.isObject', function () {
            expect(pastry.isObject({})).toBe(true);
            expect(pastry.isObject(null)).toBe(false);
            expect(pastry.isObject(noop.prototype)).toBe(true);
            expect(pastry.isObject(noop)).toBe(true);
        });
    });

    describe('core->helper functions of arrays', function () {
        var arrA, arrB,
            indexOf = pastry.index(true),
            lastIndexOf = pastry.index(false);

        beforeEach(function () {
            arrA = [1, 2, 3, 3, 4, 4, 4, 5];
            arrB = [];
        });

        it('pastry.indexOf(arr, searchElement, fromIndex)', function () {
            expect(indexOf(arrA, 1)).toBe(0);
            expect(indexOf(arrA, 4)).toBe(4);
            expect(indexOf(arrA, 5)).toBe(7);
            expect(indexOf(arrA, 6)).toBe(-1);
        });

        it('pastry.lastIndexOf(arr, searchElement, fromIndex)', function () {
            expect(lastIndexOf(arrA, 5)).toBe(7);
            expect(lastIndexOf(arrA, 3)).toBe(3);
            expect(lastIndexOf(arrA, 2)).toBe(1);
            expect(lastIndexOf(arrA, 6)).toBe(-1);
        });
        it('pastry.forEach(obj, callback, thisObj)', function () {
            pastry.forEach(arrA, function (a) {
                a += 0;
                arrB.push(a);
            });
            expect(arrB).toEqual([1, 2, 3, 3, 4, 4, 4, 5]);
            arrB = [];
            pastry.forEach(arrA, function (a) {
                a += 1;
                arrB.push(a);
            });
            expect(arrB).toEqual([2, 3, 4, 4, 5, 5, 5, 6]);
        });
        it('pastry.every(obj, callback, thisObj)', function () { // alias
            expect(pastry.every(arrA, function(item) {
                return item === 4;
            })).toEqual(false);
        });
        it('pastry.some(obj, callback, thisObj)', function () { // alias
            expect(pastry.some(arrA, function(item) {
                return item === 4;
            })).toEqual(true);
        });
        it('pastry.each(obj, callback, thisObj)', function () { // alias
            pastry.each(arrA, function (a) {
                a += 0;
                arrB.push(a);
            });
            expect(arrB).toEqual([1, 2, 3, 3, 4, 4, 4, 5]);
            arrB = [];
            pastry.each(arrA, function (a) {
                a += 1;
                arrB.push(a);
            });
            expect(arrB).toEqual([2, 3, 4, 4, 5, 5, 5, 6]);
        });
        it('pastry.remove(arr, fromIndex, toIndex)', function () {
            pastry.remove(arrA, 0, 2);
            expect(arrA).toEqual([3, 4, 4, 4, 5]);
            pastry.remove(arrA, 0);
            expect(arrA).toEqual([4, 4, 4, 5]);
            pastry.remove(arrA, 0, -1);
            expect(arrA).toEqual([]);
        });
        it('CANNOT use pastry.remove() inside of pastry.each() callback to THE SAME ARRAY', function () {
            pastry.each(arrA, function (num, i) {
                if (num === 4) {
                    pastry.remove(arrA, i);
                }
            });
            // expect(arrA).toEqual([1, 2, 3, 3, 5]); // !!!!!!!!!! REMEMBER THIS !!!!!!!!!!
            // expect(arrA).toEqual([1, 2, 3, 3, 4, 4, 4, 5]);
        });
        var obj = {
            foo: 'bar',
            hoo: 'goo'
        };
        it('delete in pastry.each()', function () {
            pastry.each(obj, function (value, key) {
                if (value === 'bar') {
                    delete obj[key];
                }
            });
            expect(obj).toEqual({
                hoo: 'goo'
            });
            expect(obj.foo).toBe(undefined);
        });
    });

    describe('core->helper functions of functions', function () {
        it('pastry.bind', function () {
            function foo1() {
                return this.hello;
            }

            var bar1 = pastry.bind(foo1, {hello: 'pastry'});
            expect(bar1()).toEqual('pastry');

            function foo2() {
                return arguments[0];
            }

            var bar2 = pastry.bind(foo2, null, 'pastry');
            expect(bar2()).toEqual('pastry');

            function foo3() {
                return arguments[1];
            }

            var bar3 = pastry.bind(foo3, null, 'hello');
            expect(bar3('pastry')).toEqual('pastry');
        });
    });
    describe('core->helper functions of cullections', function () {
        it('pastry.reduce', function () {
            var sum = pastry.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0);
            expect(sum).toBe(6);
        });
        it('pastry.union', function () {
            expect(pastry.union([1, 2], [0, 1, 2, 4], [4, 5])).toEqual([
                1, 2, 0, 4, 5
            ]);
        });
        it('pastry.uniq', function () {
            expect(pastry.uniq([1, 2, 2, 3, 4, 5, 5, 5, 6])).toEqual([
                1, 2, 3, 4, 5, 6
            ]);
        });
    });

    describe('core->helper functions of objects', function () {
        var destObj1 = {},
            destObj2 = {},
            obj1 = {
                hello: 'world'
            },
            obj2 = {
                foo: 'bar',
                bar: {
                    hi: 'hello',
                    woo: 'weee',
                    wee: {
                        hoo: 'gee',
                        hi: 'hi'
                    }
                }
            },
            obj3 = {
                foo: 'too',
                bar: {
                    woo: 'waaa',
                    wee: {
                        hi: 'hoo'
                    }
                },
                hello: [
                    'world',
                    'html',
                    'pastry'
                ]
            };
        pastry.merge(destObj1, obj1, obj2, obj3);
        it('pastry.merge(dest)', function () { // 深度合并
            // expect(destObj1.hello).toBe('world');
            expect(destObj1.foo).toBe('too');
            expect(destObj1.bar.woo).toBe('waaa');
            expect(destObj1.bar.hi).toBe('hello');
            expect(destObj1.bar.wee.hoo).toBe('gee');
            expect(destObj1.bar.wee.hi).toBe('hoo');
            console.log(destObj1.hello);
            expect(destObj1.hello).toEqual(['world', 'html', 'pastry']);
            expect(Object.prototype.toString.call(destObj1.hello)).toBe('[object Array]');
        });
        pastry.extend(destObj2, obj1, obj2, obj3);
        it('pastry.extend(dest)', function () { // 扩展
            expect(destObj1.hello).toEqual(['world', 'html', 'pastry']);
            expect(destObj2.foo).toBe('too');
            expect(destObj2.bar.woo).toBe('waaa');
            expect(destObj2.bar.hi).toBe(undefined);
            expect(destObj2.bar.wee.hoo).toBe(undefined);
            expect(destObj2.bar.wee.hi).toBe('hoo');
        });
    });

    describe('core->others', function () {
        it('pastry.getAny', function () {
            expect(pastry.getAny([
                function () {
                    pastry.ERROR('hi');
                },
                function () {
                    pastry.ERROR('error');
                },
                function () {
                    return 'hello';
                },
            ])).toBe('hello');
        });
    });
});

<|endoftext|>


<commit_before>var vm = require('vm');
var chai = require('chai');
var sinon = require('sinon');
var sinonChai = require('sinon-chai');
var Logger = require('../../../lib/logger');
var dropRequireCache = require('../../../lib/fs/drop-require-cache');

chai.should();
chai.use(sinonChai);

describe('deprecate', function () {
    var deprecate;
    var deprecatePath = require.resolve('../../../lib/utils/deprecate.js');

    beforeEach (function () {
        //dropping cache because need to have uninitialized deprecate before each test
        dropRequireCache(require, deprecatePath);
        deprecate = require(deprecatePath);
        sinon.sandbox.stub(Logger.prototype);
    });

    afterEach(function () {
        sinon.sandbox.restore();
    });

    describe('deprecate', function () {
        it('should throw error if no deprecated module provided', function () {
            (function () { deprecate({ method: 'deprecated_method', since: 'v.1.0.0' }); })
                .should.throw('Missing required field: module');
        });

        it('should delay message until initialization if deprecate is not initialized', function () {
            deprecate({ module: 'deprecated_module' });
            Logger.prototype.logWarningAction.should.not.be.called;

            deprecate.initialize();
            Logger.prototype.logWarningAction.should.be.calledOnce;
        });

        it('should print correct filename for delayed messages', function () {
            var contents = 'var deprecate = require("' + deprecatePath + '"); ' +
                'deprecate({ module: "test_module" });';
            var context = vm.createContext({ 'require': require });

            vm.runInContext(contents, context, { filename: '/test_module.js' });
            deprecate.initialize();

            Logger.prototype.logWarningAction
                .should.be.calledWithMatch(sinon.match.any, __filename); //locates test file as smth called deprecate
        });

        describe('initialized deprecate', function () {
            beforeEach(function () {
                deprecate.initialize();
            });

            it('should print message if deprecate was already initialized', function () {
                deprecate({ module: 'deprecated_module' });

                Logger.prototype.logWarningAction.should.be.calledOnce;
            });

            it('should print log action as deprecate', function () {
                deprecate({ module: 'deprecated_module', since: 'v1.0.0' });

                Logger.prototype.logWarningAction.should.be.calledWith('deprecate');
            });

            it('should print filename and code line which executed deprecate', function () {
                deprecate({ module: 'deprecated_module' });

                Logger.prototype.logWarningAction
                    .should.be.calledWithMatch(sinon.match.any, /([\/.]|([A-Z]:))\S+\(\d+.\d+\)/, sinon.match.any);
            });

            it('should print deprecated module name', function () {
                deprecate({ module: 'deprecated_module' });

                Logger.prototype.logWarningAction
                    .should.be.calledWithMatch(sinon.match.any, sinon.match.any, 'deprecated_module');
            });

            it('should print deprecated method name', function () {
                deprecate({ module: 'deprecated_module', method: 'deprecated_method' });

                Logger.prototype.logWarningAction
                    .should.be.calledWithMatch(sinon.match.any, sinon.match.any, 'deprecated_method');
            });

            it('should print since version', function () {
                deprecate({ module: 'deprecated_module', rmSince: 'v1.0.0' });

                Logger.prototype.logWarningAction
                    .should.be.calledWithMatch(sinon.match.any, sinon.match.any, 'v1.0.0');
            });

            it('should print replacement module name', function () {
                deprecate({ module: 'deprecated_module', replaceModule: 'replacement_module' });

                Logger.prototype.logWarningAction
                    .should.be.calledWithMatch(sinon.match.any, sinon.match.any, 'replacement_module');
            });

            it('should print replacement method name', function () {
                deprecate({ module: 'deprecated_module', replaceMethod: 'replacement_method' });

                Logger.prototype.logWarningAction
                    .should.be.calledWithMatch(sinon.match.any, sinon.match.any, 'replacement_method');
            });
        });

    });
});
<commit_msg>Fixed options for vm for older node versions<commit_after>var vm = require('vm');
var chai = require('chai');
var sinon = require('sinon');
var sinonChai = require('sinon-chai');
var Logger = require('../../../lib/logger');
var dropRequireCache = require('../../../lib/fs/drop-require-cache');

chai.should();
chai.use(sinonChai);

describe('deprecate', function () {
    var deprecate;
    var deprecatePath = require.resolve('../../../lib/utils/deprecate.js');

    beforeEach (function () {
        //dropping cache because need to have uninitialized deprecate before each test
        dropRequireCache(require, deprecatePath);
        deprecate = require(deprecatePath);
        sinon.sandbox.stub(Logger.prototype);
    });

    afterEach(function () {
        sinon.sandbox.restore();
    });

    describe('deprecate', function () {
        it('should throw error if no deprecated module provided', function () {
            (function () { deprecate({ method: 'deprecated_method', since: 'v.1.0.0' }); })
                .should.throw('Missing required field: module');
        });

        it('should delay message until initialization if deprecate is not initialized', function () {
            deprecate({ module: 'deprecated_module' });
            Logger.prototype.logWarningAction.should.not.be.called;

            deprecate.initialize();
            Logger.prototype.logWarningAction.should.be.calledOnce;
        });

        it('should print correct filename for delayed messages', function () {
            var contents = 'var deprecate = require(path); deprecate({ module: "test_module" });';
            var context = vm.createContext({ require: require, path: deprecatePath });

            vm.runInContext(contents, context, '/test_module.js');
            deprecate.initialize();

            Logger.prototype.logWarningAction
                .should.be.calledWithMatch(sinon.match.any, __filename); //locates test file as smth called deprecate
        });

        describe('initialized deprecate', function () {
            beforeEach(function () {
                deprecate.initialize();
            });

            it('should print message if deprecate was already initialized', function () {
                deprecate({ module: 'deprecated_module' });

                Logger.prototype.logWarningAction.should.be.calledOnce;
            });

            it('should print log action as deprecate', function () {
                deprecate({ module: 'deprecated_module', since: 'v1.0.0' });

                Logger.prototype.logWarningAction.should.be.calledWith('deprecate');
            });

            it('should print filename and code line which executed deprecate', function () {
                deprecate({ module: 'deprecated_module' });

                Logger.prototype.logWarningAction
                    .should.be.calledWithMatch(sinon.match.any, /([\/.]|([A-Z]:))\S+\(\d+.\d+\)/, sinon.match.any);
            });

            it('should print deprecated module name', function () {
                deprecate({ module: 'deprecated_module' });

                Logger.prototype.logWarningAction
                    .should.be.calledWithMatch(sinon.match.any, sinon.match.any, 'deprecated_module');
            });

            it('should print deprecated method name', function () {
                deprecate({ module: 'deprecated_module', method: 'deprecated_method' });

                Logger.prototype.logWarningAction
                    .should.be.calledWithMatch(sinon.match.any, sinon.match.any, 'deprecated_method');
            });

            it('should print since version', function () {
                deprecate({ module: 'deprecated_module', rmSince: 'v1.0.0' });

                Logger.prototype.logWarningAction
                    .should.be.calledWithMatch(sinon.match.any, sinon.match.any, 'v1.0.0');
            });

            it('should print replacement module name', function () {
                deprecate({ module: 'deprecated_module', replaceModule: 'replacement_module' });

                Logger.prototype.logWarningAction
                    .should.be.calledWithMatch(sinon.match.any, sinon.match.any, 'replacement_module');
            });

            it('should print replacement method name', function () {
                deprecate({ module: 'deprecated_module', replaceMethod: 'replacement_method' });

                Logger.prototype.logWarningAction
                    .should.be.calledWithMatch(sinon.match.any, sinon.match.any, 'replacement_method');
            });
        });

    });
});
<|endoftext|>


<commit_before>var request = require('request');
var cheerio = require('cheerio');
var schedule = require('node-schedule');
var mongoose = require('mongoose');
var Comic = require('../models/Comic').Comic;
var Settings = require('../models/Settings').Settings;
var moment = require('moment');
var titleHelper = require('../utils/titleHelper');
var extend = require('util')._extend;

var Scraper = {
  errorHandler : function(err){
    console.error("ERROR: " + err);
  },
  completedCallback : function(){
    console.log("✔ Scrape Completed!");
    updateScrapeStatus(false);
  },
  addComic : function(newComic){
    Comic.update({ title : newComic.title, publisher: newComic.publisher, issue: newComic.issue}, {$set: newComic}, {upsert:true}, function(err, comicsUpdated){
        if(err) this.errorHandler(err);
        console.log("Added "+newComic.title+" #"+newComic.issue +" by "+newComic.publisher);
    });
  },
  scrape : function(options, errCb){
    var errorCallback = errCb || Scraper.errorHandler;

    if(!options.publisher ||
       !options.URL||
       !options.monthFormat||
       !options.yearFormat||
       !options.dayFormat ||
       !options.scrapeFunction||
       !options.scrapeTime||
       !options.scrapeMinute){
      errorCallback("Missing required options");
      return;
    }

    console.log("Initialised "+options.publisher+" scraper. Hour="+options.scrapeTime+" Minute="+options.scrapeMinute);

    var scheduledTask = schedule.scheduleJob({hour: options.scrapeTime, minute: options.scrapeMinute, dayOfWeek: new schedule.Range(1, 5)}, function(){
      console.log("Beginning scrape of "+options.publisher);
      updateScrapeStatus(true);

      var scrapeComics = function scrapeComics(month){
        var now = month || moment();
        var URL = options.URL.replace('$day', now.format(options.dayFormat)).replace('$month', now.format(options.monthFormat)).replace('$year', now.format(options.yearFormat));

        var nextCallback = function(){
          now.add(1, 'months');
          scrapeComics(now);
        };

        request(URL, function(error, response, html){
            if(error){
              errorCallback(error);
            }
            if(response.statusCode === 200){
              console.log("Scraping "+URL);
              var $ = cheerio.load(html);

              options.scrapeFunction({
                '$' : $,
                'addComic' : Scraper.addComic,
                'nextCallback' : nextCallback,
                'errorCallback' : errorCallback,
                'completedCallback' : Scraper.completedCallback,
                'now' : now,
              });

            }else if(response.statusCode === 404){
              console.log(URL+" not found, assuming end of scrape");
            }
        });

      };

      scrapeComics();

    });
  },
  start : function(opt){
    if(opts){
      this.options = extend(this.options, opts);
    }
    this.scrape(this.options);
  },
  startNow : function(){
    var opts = {
      'scrapeTime' : parseInt(moment().format('H')),
      'scrapeMinute' : parseInt(moment().format('m'))+1
    };
    this.options = extend(this.options, opts);
    this.scrape(this.options);
  }
};

var updateScrapeStatus = function updateScrapeStatus(increment){
  var query = Settings.where({ name: 'scrapes' });
  query.findOne(function (err, settings) {
    if (err) return;
    var numOfScrapes = 0;
    if (settings) {
      numOfScrapes = settings.value;
    }else{
      settings = new Settings ({ name : 'scrapes', value : 0});
    }
    if(increment){
      numOfScrapes++;
    }else{
      numOfScrapes--;
    }

    settings.value = numOfScrapes;
    settings.save(function (err) {
      if(err) {
        console.error('Unable to save scrape status setting.');
      }
    });
  });
};

module.exports = Scraper;
<commit_msg>fixed typo in opts<commit_after>var request = require('request');
var cheerio = require('cheerio');
var schedule = require('node-schedule');
var mongoose = require('mongoose');
var Comic = require('../models/Comic').Comic;
var Settings = require('../models/Settings').Settings;
var moment = require('moment');
var titleHelper = require('../utils/titleHelper');
var extend = require('util')._extend;

var Scraper = {
  errorHandler : function(err){
    console.error("ERROR: " + err);
  },
  completedCallback : function(){
    console.log("✔ Scrape Completed!");
    updateScrapeStatus(false);
  },
  addComic : function(newComic){
    Comic.update({ title : newComic.title, publisher: newComic.publisher, issue: newComic.issue}, {$set: newComic}, {upsert:true}, function(err, comicsUpdated){
        if(err) this.errorHandler(err);
        console.log("Added "+newComic.title+" #"+newComic.issue +" by "+newComic.publisher);
    });
  },
  scrape : function(options, errCb){
    var errorCallback = errCb || Scraper.errorHandler;

    if(!options.publisher ||
       !options.URL||
       !options.monthFormat||
       !options.yearFormat||
       !options.dayFormat ||
       !options.scrapeFunction||
       !options.scrapeTime||
       !options.scrapeMinute){
      errorCallback("Missing required options");
      return;
    }

    console.log("Initialised "+options.publisher+" scraper. Hour="+options.scrapeTime+" Minute="+options.scrapeMinute);

    var scheduledTask = schedule.scheduleJob({hour: options.scrapeTime, minute: options.scrapeMinute, dayOfWeek: new schedule.Range(1, 5)}, function(){
      console.log("Beginning scrape of "+options.publisher);
      updateScrapeStatus(true);

      var scrapeComics = function scrapeComics(month){
        var now = month || moment();
        var URL = options.URL.replace('$day', now.format(options.dayFormat)).replace('$month', now.format(options.monthFormat)).replace('$year', now.format(options.yearFormat));

        var nextCallback = function(){
          now.add(1, 'months');
          scrapeComics(now);
        };

        request(URL, function(error, response, html){
            if(error){
              errorCallback(error);
            }
            if(response.statusCode === 200){
              console.log("Scraping "+URL);
              var $ = cheerio.load(html);

              options.scrapeFunction({
                '$' : $,
                'addComic' : Scraper.addComic,
                'nextCallback' : nextCallback,
                'errorCallback' : errorCallback,
                'completedCallback' : Scraper.completedCallback,
                'now' : now,
              });

            }else if(response.statusCode === 404){
              console.log(URL+" not found, assuming end of scrape");
            }
        });

      };

      scrapeComics();

    });
  },
  start : function(opts){
    if(opts){
      this.options = extend(this.options, opts);
    }
    this.scrape(this.options);
  },
  startNow : function(){
    var opts = {
      'scrapeTime' : parseInt(moment().format('H')),
      'scrapeMinute' : parseInt(moment().format('m'))+1
    };
    this.options = extend(this.options, opts);
    this.scrape(this.options);
  }
};

var updateScrapeStatus = function updateScrapeStatus(increment){
  var query = Settings.where({ name: 'scrapes' });
  query.findOne(function (err, settings) {
    if (err) return;
    var numOfScrapes = 0;
    if (settings) {
      numOfScrapes = settings.value;
    }else{
      settings = new Settings ({ name : 'scrapes', value : 0});
    }
    if(increment){
      numOfScrapes++;
    }else{
      numOfScrapes--;
    }

    settings.value = numOfScrapes;
    settings.save(function (err) {
      if(err) {
        console.error('Unable to save scrape status setting.');
      }
    });
  });
};

module.exports = Scraper;
<|endoftext|>


<commit_before>/*jslint browser: true, for: true */
/*global Hls, flowplayer */

/*!

   hlsjs engine plugin for Flowplayer HTML5

   Copyright (c) 2015, Flowplayer Oy

   Released under the MIT License:
   http://www.opensource.org/licenses/mit-license.php

   Includes hls.min.js
   Copyright (c) 2015 Dailymotion (http://www.dailymotion.com)
   https://github.com/dailymotion/hls.js/blob/master/LICENSE

   requires:
   - Flowplayer HTML5 version 6.x or greater
   - hls.js https://github.com/dailymotion/hls.js

*/

(function () {
    "use strict";
    var engineName = "hlsjs",
        hlsconf,
        extend = flowplayer.extend,

        engineImpl = function hlsjsEngine(player, root) {
            var bean = flowplayer.bean,
                common = flowplayer.common,
                videoTag,
                hls,

                engine = {
                    engineName: engineName,

                    pick: function (sources) {
                        var i,
                            source;

                        for (i = 0; i < sources.length; i += 1) {
                            source = sources[i];
                            if (/mpegurl/i.test(source.type) && (!source.engine || source.engine === "hlsjs")) {
                                return source;
                            }
                        }
                    },

                    load: function (video) {
                        if (hls) {
                            hls.destroy();
                        }
                        common.removeNode(common.findDirect("video", root)[0] || common.find(".fp-player > video", root)[0]);
                        videoTag = common.createElement("video");

                        bean.on(videoTag, "play", function () {
                            player.trigger('resume', [player]);
                        });
                        bean.on(videoTag, "pause", function () {
                            player.trigger('pause', [player]);
                        });
                        bean.on(videoTag, "timeupdate", function () {
                            player.trigger('progress', [player, videoTag.currentTime]);
                        });
                        bean.on(videoTag, "loadeddata", function () {
                            extend(video, {
                                duration: videoTag.duration,
                                seekable: videoTag.seekable.end(null),
                                width: videoTag.videoWidth,
                                height: videoTag.videoHeight,
                                url: videoTag.currentSrc
                            });
                            player.trigger('ready', [player, video]);

                            // fix timing for poster class
                            var poster = "is-poster";
                            if (common.hasClass(root, poster)) {
                                player.on("stop.hlsjs", function () {
                                    setTimeout(function () {
                                        common.addClass(root, poster);
                                        bean.one(videoTag, "play.hlsjs", function () {
                                            common.removeClass(root, poster);
                                        });
                                    }, 0);
                                });
                            }

                            if (player.conf.autoplay) {
                                // let the fp API take care of autoplay
                                videoTag.play();
                            }
                        });
                        bean.on(videoTag, "seeked", function () {
                            player.trigger('seek', [player, videoTag.currentTime]);
                        });
                        bean.on(videoTag, "progress", function (e) {
                            try {
                                var buffered = videoTag.buffered,
                                    buffer = buffered.end(null), // first loaded buffer
                                    ct = videoTag.currentTime,
                                    buffend = 0,
                                    i;

                                // buffered.end(null) will not always return the current buffer
                                // so we cycle through the time ranges to obtain it
                                if (ct) {
                                    for (i = 1; i < buffered.length; i += 1) {
                                        buffend = buffered.end(i);

                                        if (buffend >= ct && buffered.start(i) <= ct) {
                                            buffer = buffend;
                                        }
                                    }
                                }
                                video.buffer = buffer;
                            } catch (ignored) {}
                            player.trigger('buffer', [player, e]);
                        });
                        bean.on(videoTag, "ended", function () {
                            player.trigger('finish', [player]);
                        });
                        bean.on(videoTag, "volumechange", function () {
                            player.trigger('volume', [player, videoTag.volume]);
                        });

                        videoTag.className = 'fp-engine hlsjs-engine';
                        common.prepend(common.find(".fp-player", root)[0], videoTag);

                        hls = new Hls(hlsconf);

                        hls.on(Hls.Events.MSE_ATTACHED, function () {
                            hls.loadSource(video.src);

                        }).on(Hls.Events.ERROR, function (e, data) {
                            var fperr,
                                errobj;

                            if (data.fatal) {
                                // try recovery?
                                switch (data.type) {
                                case Hls.ErrorTypes.NETWORK_ERROR:
                                    // in theory should be 3 (Network error)
                                    fperr = 4;
                                    break;
                                case Hls.ErrorTypes.MEDIA_ERROR:
                                    fperr = 3;
                                    break;
                                default:
                                    fperr = 5;
                                    break;
                                }
                                errobj = {code: fperr};
                                if (fperr > 2) {
                                    errobj.video = extend(video, {
                                        src: video.src,
                                        url: data.url || video.src
                                    });
                                }
                                player.trigger('error', [player, errobj]);
                            }
                            /* TODO: */
                            // log non fatals
                        });

                        hls.attachVideo(videoTag);
                    },

                    resume: function () {
                        videoTag.play();
                    },

                    pause: function () {
                        videoTag.pause();
                    },

                    seek: function (time) {
                        videoTag.currentTime = time;
                    },

                    volume: function (level) {
                        if (videoTag) {
                            videoTag.volume = level;
                        }
                    },

                    speed: function (val) {
                        videoTag.playbackRate = val;
                        player.trigger('speed', [player, val]);
                    },

                    unload: function () {
                        player.trigger('unload', [player]);
                        if (player.conf.splash) {
                            hls.destroy();
                            common.find("video.fp-engine", root).forEach(common.removeNode);
                        }
                    }
                };

            return engine;
        };

    if (Hls.isSupported()) {
        // only load engine if it can be used
        engineImpl.engineName = engineName; // must be exposed
        engineImpl.canPlay = function (type, conf) {
            if (conf.hlsjs === false || conf.clip.hlsjs === false) {
                // engine disabled for player or clip
                return false;
            }

            // merge hlsjs clip config at earliest opportunity
            hlsconf = extend({}, conf.hlsjs, conf.clip.hlsjs);

            // support Safari only when hlsjs debugging
            // https://github.com/dailymotion/hls.js/issues/9
            return /mpegurl/i.test(type) && (!flowplayer.support.browser.safari || hlsconf.debug);
        };

        // put on top of engine stack
        // so hlsjs is tested before html5 video hls and flash hls
        flowplayer.engines.unshift(engineImpl);
    }

}());
<commit_msg>Allow in IE11, even if it pretends to be iPhone<commit_after>/*jslint browser: true, for: true */
/*global Hls, flowplayer */

/*!

   hlsjs engine plugin for Flowplayer HTML5

   Copyright (c) 2015, Flowplayer Oy

   Released under the MIT License:
   http://www.opensource.org/licenses/mit-license.php

   Includes hls.min.js
   Copyright (c) 2015 Dailymotion (http://www.dailymotion.com)
   https://github.com/dailymotion/hls.js/blob/master/LICENSE

   requires:
   - Flowplayer HTML5 version 6.x or greater
   - hls.js https://github.com/dailymotion/hls.js

*/

(function () {
    "use strict";
    var engineName = "hlsjs",
        hlsconf,
        extend = flowplayer.extend,

        engineImpl = function hlsjsEngine(player, root) {
            var bean = flowplayer.bean,
                common = flowplayer.common,
                videoTag,
                hls,

                engine = {
                    engineName: engineName,

                    pick: function (sources) {
                        var i,
                            source;

                        for (i = 0; i < sources.length; i += 1) {
                            source = sources[i];
                            if (/mpegurl/i.test(source.type) && (!source.engine || source.engine === "hlsjs")) {
                                return source;
                            }
                        }
                    },

                    load: function (video) {
                        if (hls) {
                            hls.destroy();
                        }
                        common.removeNode(common.findDirect("video", root)[0] || common.find(".fp-player > video", root)[0]);
                        videoTag = common.createElement("video");

                        bean.on(videoTag, "play", function () {
                            player.trigger('resume', [player]);
                        });
                        bean.on(videoTag, "pause", function () {
                            player.trigger('pause', [player]);
                        });
                        bean.on(videoTag, "timeupdate", function () {
                            player.trigger('progress', [player, videoTag.currentTime]);
                        });
                        bean.on(videoTag, "loadeddata", function () {
                            extend(video, {
                                duration: videoTag.duration,
                                seekable: videoTag.seekable.end(null),
                                width: videoTag.videoWidth,
                                height: videoTag.videoHeight,
                                url: videoTag.currentSrc
                            });
                            player.trigger('ready', [player, video]);

                            // fix timing for poster class
                            var poster = "is-poster";
                            if (common.hasClass(root, poster)) {
                                player.on("stop.hlsjs", function () {
                                    setTimeout(function () {
                                        common.addClass(root, poster);
                                        bean.one(videoTag, "play.hlsjs", function () {
                                            common.removeClass(root, poster);
                                        });
                                    }, 0);
                                });
                            }

                            if (player.conf.autoplay) {
                                // let the fp API take care of autoplay
                                videoTag.play();
                            }
                        });
                        bean.on(videoTag, "seeked", function () {
                            player.trigger('seek', [player, videoTag.currentTime]);
                        });
                        bean.on(videoTag, "progress", function (e) {
                            try {
                                var buffered = videoTag.buffered,
                                    buffer = buffered.end(null), // first loaded buffer
                                    ct = videoTag.currentTime,
                                    buffend = 0,
                                    i;

                                // buffered.end(null) will not always return the current buffer
                                // so we cycle through the time ranges to obtain it
                                if (ct) {
                                    for (i = 1; i < buffered.length; i += 1) {
                                        buffend = buffered.end(i);

                                        if (buffend >= ct && buffered.start(i) <= ct) {
                                            buffer = buffend;
                                        }
                                    }
                                }
                                video.buffer = buffer;
                            } catch (ignored) {}
                            player.trigger('buffer', [player, e]);
                        });
                        bean.on(videoTag, "ended", function () {
                            player.trigger('finish', [player]);
                        });
                        bean.on(videoTag, "volumechange", function () {
                            player.trigger('volume', [player, videoTag.volume]);
                        });

                        videoTag.className = 'fp-engine hlsjs-engine';
                        common.prepend(common.find(".fp-player", root)[0], videoTag);

                        hls = new Hls(hlsconf);

                        hls.on(Hls.Events.MSE_ATTACHED, function () {
                            hls.loadSource(video.src);

                        }).on(Hls.Events.ERROR, function (e, data) {
                            var fperr,
                                errobj;

                            if (data.fatal) {
                                // try recovery?
                                switch (data.type) {
                                case Hls.ErrorTypes.NETWORK_ERROR:
                                    // in theory should be 3 (Network error)
                                    fperr = 4;
                                    break;
                                case Hls.ErrorTypes.MEDIA_ERROR:
                                    fperr = 3;
                                    break;
                                default:
                                    fperr = 5;
                                    break;
                                }
                                errobj = {code: fperr};
                                if (fperr > 2) {
                                    errobj.video = extend(video, {
                                        src: video.src,
                                        url: data.url || video.src
                                    });
                                }
                                player.trigger('error', [player, errobj]);
                            }
                            /* TODO: */
                            // log non fatals
                        });

                        hls.attachVideo(videoTag);
                    },

                    resume: function () {
                        videoTag.play();
                    },

                    pause: function () {
                        videoTag.pause();
                    },

                    seek: function (time) {
                        videoTag.currentTime = time;
                    },

                    volume: function (level) {
                        if (videoTag) {
                            videoTag.volume = level;
                        }
                    },

                    speed: function (val) {
                        videoTag.playbackRate = val;
                        player.trigger('speed', [player, val]);
                    },

                    unload: function () {
                        player.trigger('unload', [player]);
                        if (player.conf.splash) {
                            hls.destroy();
                            common.find("video.fp-engine", root).forEach(common.removeNode);
                        }
                    }
                };

            return engine;
        };

    if (Hls.isSupported()) {
        // only load engine if it can be used
        engineImpl.engineName = engineName; // must be exposed
        engineImpl.canPlay = function (type, conf) {
            var UA = navigator.userAgent,
                IE11 = UA.indexOf("Trident/7") > -1;

            if (conf.hlsjs === false || conf.clip.hlsjs === false) {
                // engine disabled for player or clip
                return false;
            }

            // merge hlsjs clip config at earliest opportunity
            hlsconf = extend({}, conf.hlsjs, conf.clip.hlsjs);

            // support Safari only when hlsjs debugging
            // https://github.com/dailymotion/hls.js/issues/9
            return /mpegurl/i.test(type) &&
                    (IE11 || !flowplayer.support.browser.safari || hlsconf.debug);
        };

        // put on top of engine stack
        // so hlsjs is tested before html5 video hls and flash hls
        flowplayer.engines.unshift(engineImpl);
    }

}());
<|endoftext|>