Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support multi page flow #2

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
286 changes: 262 additions & 24 deletions lib/driver.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
/**!
* totoro-selenium-driver - lib/driver.js
*
* Copyright(c) 2014 leoner and other contributors.
* MIT Licensed
*
* Authors:
* leoner <[email protected]>
*/
* totoro-selenium-driver - lib/driver.js
*
* Copyright(c) 2014 leoner and other contributors.
* MIT Licensed
*
* Authors:
* leoner <[email protected]>
*/

"use strict";

/**
* Module dependencies.
*/
* Module dependencies.
*/

var debug = require('debug')('totoro-selenium-driver');
var TotoroDriver = require('totoro-driver-base');
var webdriver = require('selenium-webdriver');
var path = require('path');
var util = require('util');
var async = require('async');
var fs = require('fs');
// var EventEmitter = require('events').EventEmitter; // 暂时不需要事件发布.

//var firefox = require('selenium-webdriver/firefox');
var chrome = require('selenium-webdriver/chrome');
Expand All @@ -32,7 +34,8 @@ var chromeDriver;
module.exports = SeleniumDriver;

function SeleniumDriver(options) {
this.includeScripts = options.includeScripts || [];
// this._events = new EventEmitter();
this.includeScripts = options.includeScripts || []; // 固定不变的.每个页面都需要加载的脚本列表
TotoroDriver.call(this, options);
}

Expand All @@ -47,34 +50,269 @@ proto.getBrowser = function () {

proto.onAdd = function (data) {
var that = this;

chromeDriver = new chrome.Driver();
debug('got a order: %j', data);
chromeDriver.get(data.url).then(function() {
that._watchUrlChanged(function(url, script) {
that.loadScripts(script);
});
});
};

proto.loadScripts = function(script) {
var that = this;
if (this.includeScripts) {
insertScripts(this.includeScripts, function() {
var scriptStr = '(function(){})';
if (script) {
scriptStr = script.replace(/\r\n/g, '');
setTimeout(function() {
chromeDriver.executeScript(eval(scriptStr));
}, 200);
}
});
}
};

chromeDriver.get(data.url);
function insertScripts(includeScripts, callback) {
async.eachSeries(includeScripts, function(script, cb){
var scriptStr;
if (script.indexOf('http') > -1) {
scriptStr = getUrlScript(script);
} else {
scriptStr = getFileScript(script);
}
chromeDriver.executeScript(scriptStr).then(cb);
}, function() {
callback();
});
}

function getUrlScript (script) {
// create dom script
var str = '(function(){'
str += 'var script = document.createElement("script");'
str += 'script.src = "' + script + '";';
str += 'document.getElementsByTagName("body")[0].appendChild(script);';
str += '})';
return str;
}

function getFileScript(script) {
return fs.readFileSync(script) + '';
}

// TODO 如果支持此功能需要更精细的检查.
proto._watchUrlChanged = function(cb) {
var that = this;
this._timer = setInterval(function() {
chromeDriver.wait(function() {
return chromeDriver.getCurrentUrl().then(function(url) {
if (Object.keys(that.subTasks).length === 0) {
clearInterval(that._timer);
} else {
var script = that._findMappingScript(url);
if (script) {
cb(url, script);
}
}
return true;
});
});
}, 1000);
};

proto._findMappingScript = function(url) {
var that = this;
var script = null;
// 如果支持多页面, 需要提前传入 runner 和 测试脚本的对应关系, 也就是 subTasks
if (this.subTasks) {
Object.keys(this.subTasks).some(function(subUrl) {
if (isMatch(url, subUrl)) {
script = that.subTasks[subUrl];
delete that.subTasks[subUrl];
return true;
}
});
}
return script;
};

// 检查 url 是否匹配
function isMatch(url, subUrl) {
if (url.indexOf(subUrl) === 0) {
return true;
}

if (subUrl.indexOf('/') === 0) {
return url.indexOf(subUrl) > -1;
}
return false;
}

proto.onRemove = function (data) {
// the structure is the same as 'add' event's but without the ua
clearInterval(this._timer);
chromeDriver.quit();
};

proto.cleanup = function () {
};
/**!
* totoro-selenium-driver - lib/driver.js
*
* Copyright(c) 2014 leoner and other contributors.
* MIT Licensed
*
* Authors:
* leoner <[email protected]>
*/

"use strict";

/**
* Module dependencies.
*/

var debug = require('debug')('totoro-selenium-driver');
var TotoroDriver = require('totoro-driver-base');
var webdriver = require('selenium-webdriver');
var path = require('path');
var util = require('util');
var async = require('async');
var fs = require('fs');
// var EventEmitter = require('events').EventEmitter; // 暂时不需要事件发布.

//var firefox = require('selenium-webdriver/firefox');
var chrome = require('selenium-webdriver/chrome');

process.env.PATH = process.env.PATH + ':' + __dirname;
var chromeDriver;

//var firefoxDriver = new firefox.Driver();

module.exports = SeleniumDriver;

function SeleniumDriver(options) {
// this._events = new EventEmitter();
this.includeScripts = options.includeScripts || []; // 固定不变的.每个页面都需要加载的脚本列表
TotoroDriver.call(this, options);
}

util.inherits(SeleniumDriver, TotoroDriver);

var proto = SeleniumDriver.prototype;

proto.getBrowser = function () {
var ver = require(path.join('../node_modules/selenium-webdriver/package.json')).version;
return { name: 'selenium', version: ver };
};

proto.onAdd = function (data) {
var that = this;
chromeDriver = new chrome.Driver();
debug('got a order: %j', data);
chromeDriver.get(data.url).then(function() {
that._watchUrlChanged(function(url, script) {
that.loadScripts(script);
});
});
};

proto.loadScripts = function(script) {
var that = this;
if (this.includeScripts) {
async.eachSeries(this.includeScripts, function(script, cb){
var str = '(function(){'
str += 'var script = document.createElement("script");'
str += 'script.src = "' + script + '";';
str += 'document.getElementsByTagName("body")[0].appendChild(script);';
str += '})';
chromeDriver.executeScript(eval(str)).then(cb);
}, function() {
insertScripts(this.includeScripts, function() {
var scriptStr = '(function(){})';
if (that.script) {
scriptStr = that.script.replace(/\r\n/g, '');
if (script) {
scriptStr = script.replace(/\r\n/g, '');
setTimeout(function() {
chromeDriver.executeScript(eval(scriptStr));
}, 500);
}, 200);
}
});
}
};

function insertScripts(includeScripts, callback) {
async.eachSeries(includeScripts, function(script, cb){
var scriptStr;
if (script.indexOf('http') > -1) {
scriptStr = getUrlScript(script);
} else {
scriptStr = getFileScript(script);
}
chromeDriver.executeScript(scriptStr).then(cb);
}, function() {
callback();
});
}

function getUrlScript (script) {
// create dom script
var str = '(function(){'
str += 'var script = document.createElement("script");'
str += 'script.src = "' + script + '";';
str += 'document.getElementsByTagName("body")[0].appendChild(script);';
str += '})';
return str;
}

function getFileScript(script) {
return fs.readFileSync(script) + '';
}

// TODO 如果支持此功能需要更精细的检查.
proto._watchUrlChanged = function(cb) {
var that = this;
this._timer = setInterval(function() {
chromeDriver.wait(function() {
return chromeDriver.getCurrentUrl().then(function(url) {
if (Object.keys(that.subTasks).length === 0) {
clearInterval(that._timer);
} else {
var script = that._findMappingScript(url);
if (script) {
cb(url, script);
}
}
return true;
});
});
}, 1000);
};

proto._findMappingScript = function(url) {
var that = this;
var script = null;
// 如果支持多页面, 需要提前传入 runner 和 测试脚本的对应关系, 也就是 subTasks
if (this.subTasks) {
Object.keys(this.subTasks).some(function(subUrl) {
if (isMatch(url, subUrl)) {
script = that.subTasks[subUrl];
delete that.subTasks[subUrl];
return true;
}
});
}
return script;
};

// 检查 url 是否匹配
function isMatch(url, subUrl) {
if (url.indexOf(subUrl) === 0) {
return true;
}

if (subUrl.indexOf('/') === 0) {
return url.indexOf(subUrl) > -1;
}
return false;
}

proto.onRemove = function (data) {
// the structure is the same as 'add' event's but without the ua
clearInterval(this._timer);
chromeDriver.quit();
};

Expand Down