uirecorder
Version:
Tool for record ui test case
907 lines (893 loc) • 95 kB
JavaScript
var path = require('path');
var fs = require('fs');
var os = require('os');
var http = require('http');
var url = require('url');
var cp = require('child_process');
var inquirer = require('inquirer');
var async = require('async');
var co = require('co');
var chai = require("chai");
var should = chai.should();
var JWebDriver = require('jwebdriver');
chai.use(JWebDriver.chaiSupportChainPromise);
var chromedriver = require('chromedriver');
const $ = require('jquery');
const resemble = require('resemblejs-node');
resemble.outputSettings({
errorType: 'flatDifferenceIntensity'
});
var WebSocketServer = require('websocket').server;
var i18n = require('./i18n');
var colors = require('colors');
var detectPort = require('detect-port');
var symbols = {
ok: '✓',
err: '✖'
};
var recorderBrowserTimeout = 1000;
var checkerBrowserTimeout = 0;
if (process.platform === 'win32') {
symbols.ok = '\u221A';
symbols.err = '\u00D7';
recorderBrowserTimeout = 0;
checkerBrowserTimeout = 1000;
}
var defaultOpenChecker = true;
var defaultBrowserSize = '1024x768';
var wsConnection;
var rootPath = getRootPath();
var pkg = require('../package.json');
function startRecorder(options){
var locale = options.locale;
var cmdFilename = options.cmdFilename;
var mobile = options.mobile;
var debug = options.debug;
var raw = options.raw;
var defaultOption = options.default;
var mobileDevice = options.mobileDevice;
var wdproxy = process.env['wdproxy'] || '';
if(locale){
i18n.setLocale(locale);
}
var configPath = 'config.json';
var configFile = path.resolve(rootPath + '/' + configPath);
var configJson = {};
if (fs.existsSync(configFile)) {
var content = fs.readFileSync(configFile).toString();
try {
configJson = JSON.parse(content);
}
catch (e) {
console.log(configPath.bold + ' ' + __('json_parse_failed').red, e);
process.exit(1);
}
}
else {
console.log(configPath.bold + ' ' + __('file_missed').red);
process.exit(1);
}
if(!configJson.webdriver){
console.log(__('please_reinit').red);
process.exit(1);
}
var recorderConfig = configJson.recorder || {};
var pathAttrs = recorderConfig.pathAttrs;
if(pathAttrs){
pathAttrs = pathAttrs.replace(/^\s+|\s+$/g, '');
pathAttrs = pathAttrs.split(/\s*,\s*/).map(function(name){
return {
name: name,
on: true
};
});
pathAttrs.unshift({
name: 'value',
on: true
});
pathAttrs.unshift({
name: 'name',
on: true
});
pathAttrs.unshift({
name: 'text',
on: true
});
pathAttrs.unshift({
name: 'id',
on: true
});
}
var attrValueBlack = recorderConfig.attrValueBlack;
var classValueBlack = recorderConfig.classValueBlack;
var hideBeforeExpect = recorderConfig.hideBeforeExpect;
var recorderFirst = recorderConfig.recorderFirst
// 用来确定录制窗口和校验窗口的打开顺序,用来解决某些特殊场景下,窗口显示上面顺序问题
if(recorderFirst !== undefined){
recorderBrowserTimeout = recorderFirst ? 0 : 1000;
checkerBrowserTimeout = recorderFirst ? 1000 : 0;
}
var testVars = configJson.vars;
var isConfigEdited = false;
var hostsPath = 'hosts';
var hostsFile = path.resolve(rootPath + '/' + hostsPath);
var hosts = '';
if(fs.existsSync(hostsFile)){
hosts = fs.readFileSync(hostsFile).toString();
}
// read spec list
var commonSpecRelPath = 'commons/';
var commonSpecPath = rootPath + '/' + commonSpecRelPath;
if(fs.existsSync(commonSpecPath) == false || fs.statSync(commonSpecPath).isDirectory() === false){
commonSpecRelPath = '';
commonSpecPath = rootPath;
}
var dirList = fs.readdirSync(commonSpecPath);
var specLists = [];
dirList.forEach(function(item){
if(/.*\.js$/.test(item)){
specLists.push(commonSpecRelPath + item);
}
});
var wdPort;
if(fs.existsSync(chromedriver.path)){
detectPort(6789).then(function(port) {
wdPort = port;
chromedriver = chromedriver.start(['--url-base=wd/hub', '--port='+wdPort]);
chromedriver.stdout.unpipe(process.stdout)
chromedriver.stderr.unpipe(process.stderr)
});
}
else{
console.log('chromedriver bin file no existed, please reinstall uirecorder again.'.red);
process.exit(1);
}
var questions = [];
if(cmdFilename){
console.log('? '.green+__('input_spec_name').white.bold + ' ' + cmdFilename.cyan);
}
else{
questions.push({
'type': 'input',
'name': 'fileName',
'message': __('input_spec_name'),
'default': cmdFilename || 'sample/test.spec.js',
'filter': function(input){
return input.replace(/(^\s+|\s+$)/g, '').replace(/\\/g,'/');
},
'validate': function(input){
return input !== '' && /\.js$/.test(input);
}
});
}
questions.push({
'type': 'confirm',
'name': 'continueRecord',
'message': __('continue_to_record'),
'default': false,
'when': function(answers){
var fileName = cmdFilename ||answers.fileName;
if(fs.existsSync(fileName)){
var content = fs.readFileSync(fileName).toString();
return /\s*function _\(str\)/.test(content);
}
return false;
}
});
if(mobile){
questions = questions.concat([
{
'type': 'input',
'name': 'mobileAppPath',
'message': __('mobile_app_path'),
'default': '',
'filter': function(input){
return input.replace(/(^\s+|\s+$)/g, '');
},
'validate': function(input){
return (/^https?:\/\//.test(input) || (/\.(apk|app|zip)$/.test(input) && fs.existsSync(input)));
},
'when': function(answers){
if(answers.continueRecord){
var fileName = cmdFilename || answers.fileName;
var content = fs.readFileSync(fileName).toString();
var match = content.match(/appPath = '([^']+)';/);
if(match){
answers.mobileAppPath = match[1];
match = content.match(/platformName = '([^']+)';/);
answers.mobilePlatform = match[1];
}
}
return !answers.mobileAppPath;
}
},
{
'type': 'list',
'name': 'mobilePlatform',
'choices': ['Android', 'iOS'],
'message': __('mobile_platform'),
'when': function(answers){
if(!answers.mobilePlatform){
var mobileAppPath = answers.mobileAppPath;
var mobilePlatform = null;
if(/(\bandroid\b|\.apk$)/i.test(mobileAppPath)){
mobilePlatform = 'Android';
}
if(/(\bios\b|\.app$)/i.test(mobileAppPath)){
mobilePlatform = 'iOS';
}
if(mobilePlatform){
answers.mobilePlatform = mobilePlatform;
}
else{
return true;
}
}
}
}
]);
} else {
if(defaultOption){
console.log('? '.green+__('open_checker_browser').white.bold + ' ' + (defaultOpenChecker?'Yes':'No').cyan);
console.log('? '.green+__('browser_size').white.bold + ' ' + defaultBrowserSize.cyan);
} else {
questions = questions.concat([
{
'type': 'confirm',
'name': 'checker',
'message': __('open_checker_browser'),
'default': true
},
{
'type': 'input',
'name': 'browserSize',
'message': __('browser_size'),
'default': '1024x768',
'filter': function(input){
return input.replace(/(^\s+|\s+$)/g, '');
},
'validate': function(input){
return input === 'maximize' || /^\d+\s*[x, ]\s*\d+$/.test(input);
},
'when': function(answers){
if(answers.continueRecord){
var fileName = cmdFilename || answers.fileName;
var content = fs.readFileSync(fileName).toString();
var match = content.match(/\.windowSize\((\d+), (\d+)\)/);
if(match){
answers.browserSize = match[1] + ' x ' + match[2];
}
}
return !answers.continueRecord;
}
}
]);
}
}
inquirer.prompt(questions).then(function(answers){
var fileName = answers.fileName || cmdFilename;
var testFile = path.resolve(fileName);
fileName = path.relative(rootPath, testFile).replace(/\\/g,'/');
var specName = fileName.replace(/\.js$/,'');
var caseName = specName + ' : chrome';
var continueRecord = answers.continueRecord;
var openChecker = defaultOption ? defaultOpenChecker : answers.checker;
var browserSize = defaultOption ? defaultBrowserSize : answers.browserSize || '';
var match = browserSize.match(/^(\d+)\s*[x, ]\s*(\d+)$/);
if(match){
browserSize = [ parseInt(match[1], 10), parseInt(match[2], 10)];
}
else{
browserSize = null;
}
var mobileAppPath = answers.mobileAppPath;
var mobilePlatform = answers.mobilePlatform;
var arrTestCodes = [];
var recorderBrowser, checkerBrowser, recorderMobileApp;
var lastWindowId = 0;
var lastFrameId = null;
var lastTestTitle = '';
var arrLastTestCodes = [];
var arrRawCmds = [];
var allCaseCount = 0;
var failedCaseCount = 0;
var isModuleLoading = false;
function escapeStr(str){
return str.replace(/\\/g, '\\\\').replace(/\r?\n/g, '\\n').replace(/\'/g, "\\'");
}
function pushRawCmd(cmd, data){
arrRawCmds.push({
type: cmd,
data: data
});
}
function pushTestCode(cmd, text, ext, codes){
var title = cmd +': ';
title += text ? text + ' ( '+ext+' )' : ext;
lastTestTitle = title;
arrLastTestCodes = [];
if(Array.isArray(codes)){
codes.forEach(function(line){
arrLastTestCodes.push(' '+line);
});
}
else{
arrLastTestCodes.push(' '+codes);
}
title = title.replace(/^\w+:/, function(all){
return all.cyan;
});
console.log(' '+title);
}
function saveTestCode(success, error){
if(checkerBrowser || recorderMobileApp){
if(success){
console.log(' '+symbols.ok.green+__('exec_succeed').green);
}
else{
console.log(' '+symbols.err.red+__('exec_failed').red, error && error.message || error);
}
}
allCaseCount ++;
if(!success){
failedCaseCount ++;
}
if(arrLastTestCodes.length > 0){
(checkerBrowser || recorderMobileApp) && sendWsMessage('checkResult', {
title: lastTestTitle,
success: success
});
if(!success){
lastTestTitle = '\u00D7 ' + lastTestTitle;
}
arrTestCodes.push('it(\''+escapeStr(lastTestTitle)+'\', async function(){');
arrTestCodes = arrTestCodes.concat(arrLastTestCodes);
arrTestCodes.push("});");
arrTestCodes.push("");
lastTestTitle = '';
arrLastTestCodes = [];
}
}
var cmdQueue = async.priorityQueue(function(cmdInfo, next) {
if(isModuleLoading){
return next();
}
var window = cmdInfo.window;
var frame = cmdInfo.frame;
var cmd = cmdInfo.cmd;
var data = cmdInfo.data;
if(cmd === '!updateMobile'){
if(recorderMobileApp){
var screenshot;
recorderMobileApp.getScreenshot(function(error, png64){
screenshot = png64;
}).source(function(error, source){
if(screenshot && source){
sendWsMessage('mobileAppInfo', {
screenshot: screenshot,
source: JSON.parse(source)
});
}
else{
console.log(error);
}
next();
});
}
else{
next();
}
return;
}
else if(cmd === '!updateAttrValueBlack'){
configJson.recorder.attrValueBlack = data;
recorderConfig.attrValueBlack = data;
sendWsMessage('config', recorderConfig);
isConfigEdited = true;
return next();
}
else if(cmd === 'end'){
return next();
}
var arrTasks = [];
arrTasks.push(function(callback){
if(mobile){
// skip window switch when mobile mode
return callback();
}
function doNext(){
saveTestCode(true);
callback();
}
function catchError(error){
saveTestCode(false, error);
callback();
}
if(window !== lastWindowId){
lastWindowId = window;
lastFrameId = null;
pushRawCmd('switchWindow', window);
pushTestCode('switchWindow', '', window, 'await driver.sleep(500).switchWindow('+window+');')
checkerBrowser && checkerBrowser.sleep(500).switchWindow(window).then(doNext).catch(catchError) || doNext();
}
else{
callback();
}
});
arrTasks.push(function(callback){
if(mobile){
// skip frame switch when mobile mode
return callback();
}
function doNext(){
saveTestCode(true);
callback();
}
function catchError(error){
saveTestCode(false, error);
callback();
}
if(frame !== lastFrameId){
lastFrameId = frame;
var arrCodes = [];
if(frame !== null){
arrCodes.push('await driver.switchFrame(null)');
arrCodes.push(' .wait(\''+frame+'\', 30000).then(function(element){');
arrCodes.push(' return this.switchFrame(element).wait(\'body\');');
arrCodes.push(' });');
}
else{
arrCodes.push('await driver.switchFrame(null);');
}
pushRawCmd('switchFrame', frame);
pushTestCode('switchFrame', '', frame, arrCodes);
checkerBrowser && checkerBrowser.switchFrame(null, function(error){
if(frame !== null){
return this.wait(frame, 10000).then(function(element){
return this.switchFrame(element).wait('body');
});
}
}).then(doNext).catch(catchError) || doNext();
}
else{
callback();
}
});
arrTasks.push(function(callback){
function doNext(){
saveTestCode(true);
callback();
}
function catchError(error){
saveTestCode(false, error);
callback();
}
pushRawCmd(cmd, data);
var arrCodes = [];
if(mobile){
switch(cmd){
case 'click':
if(data.path){
pushTestCode('tap', data.text, data.path, 'await driver.wait(\''+escapeStr(data.path)+'\', 30000).sendElementActions(\'tap\');');
recorderMobileApp.wait(data.path, 10000).sendElementActions('tap').then(doNext).catch(catchError);
}
else{
pushTestCode('tap', '', data.x+', '+data.y, 'await driver.sendActions(\'tap\', {x: '+data.x+', y: '+data.y+'});');
recorderMobileApp.sendActions('tap', {x: data.x, y: data.y}).then(doNext).catch(catchError);
}
break;
case 'dblClick':
if(data.path){
pushTestCode('doubleTap', data.text, data.path, 'await driver.wait(\''+escapeStr(data.path)+'\', 30000).sendElementActions(\'doubleTap\');');
recorderMobileApp.wait(data.path, 10000).sendElementActions('doubleTap').then(doNext).catch(catchError);
}
else{
pushTestCode('doubleTap', '', data.x+', '+data.y, 'await driver.sendActions(\'doubleTap\', {x: '+data.x+', y: '+data.y+'});');
recorderMobileApp.sendActions('doubleTap', {x: data.x, y: data.y}).then(doNext).catch(catchError);
}
break;
case 'press':
if(data.path){
pushTestCode('press', data.text, data.path+', '+data.duration, 'await driver.wait(\''+escapeStr(data.path)+'\', 30000).sendElementActions(\'press\', {duration: '+data.duration+'});');
recorderMobileApp.wait(data.path, 10000).sendElementActions('press', {duration : data.duration}).then(doNext).catch(catchError);
}
else{
pushTestCode('press', '', data.x+', '+data.y+', '+data.duration, 'await driver.sendActions(\'press\', {x: '+data.x+', y: '+data.y+', duration: '+data.duration+'});');
recorderMobileApp.sendActions('press', {x: data.x, y: data.y, duration: data.duration}).then(doNext).catch(catchError);
}
break;
case 'drag':
pushTestCode('drag', '', data.fromX+', '+data.fromY+', '+data.toX+', '+data.toY+', '+data.duration, 'await driver.sendActions(\'drag\', {fromX: '+data.fromX+', fromY:'+data.fromY+', toX:'+data.toX+', toY:'+data.toY+', duration: '+data.duration+'});');
recorderMobileApp.sendActions('drag', {fromX: data.fromX, fromY: data.fromY, toX: data.toX, toY: data.toY, duration: data.duration}).then(doNext).catch(catchError);
break;
case 'sendKeys':
pushTestCode('sendKeys', '', data, 'await driver.sendKeys(_(\`'+escapeStr(data)+'\`));');
recorderMobileApp.sendKeys(getVarStr(eval('\`'+data+'\`'))).then(doNext).catch(catchError);
break;
case 'sleep':
pushTestCode('sleep', '', data, 'await driver.sleep('+data+');');
recorderMobileApp.sleep(data).then(doNext).catch(catchError);
break;
case 'acceptAlert':
pushTestCode('acceptAlert', '', '', 'await driver.acceptAlert();');
recorderMobileApp.acceptAlert().then(doNext).catch(catchError);
break;
case 'dismissAlert':
pushTestCode('dismissAlert', '', '', 'await driver.dismissAlert();');
recorderMobileApp.dismissAlert().then(doNext).catch(catchError);
break;
case 'back':
pushTestCode('back', '', '', 'await driver.back();');
recorderMobileApp.back().then(doNext).catch(catchError);
break;
case 'expect':
co(function*(){
var expectSleep = data.sleep;
var expectType = data.type;
var expectPath = data.path;
var expectCompare = data.compare;
var expectTo = data.to;
arrCodes = [];
if(expectType === 'count'){
arrCodes.push('await driver.wait(\''+escapeStr(expectPath)+'\', {timeout: 1000, noerror: true})');
arrCodes.push(' .then(function(elements){');
arrCodes.push(' return elements.length;');
arrCodes.push(' })');
}
else if(expectType === 'imgdiff'){
arrCodes.push("let self = this;");
arrCodes.push("let imgBasePath = self.diffbasePath + '/' + self.caseName + '_' + self.stepId + '.png';");
arrCodes.push("let imgNewPath = self.screenshotPath + '/' + self.caseName + '_' + self.stepId + '_new.png';");
arrCodes.push("let imgDiffPath = self.screenshotPath + '/' + self.caseName + '_' + self.stepId + '_diff.png';");
arrCodes.push("let elemshot = await driver.sleep(300).getScreenshot({");
arrCodes.push(" elem: '"+escapeStr(expectPath)+"',");
arrCodes.push(" filename: imgNewPath");
arrCodes.push("});");
arrCodes.push("elemshot = new Buffer(elemshot, 'base64');");
arrCodes.push("if(!fs.existsSync(imgBasePath) || process.env['npm_config_rebuilddiff']){");
arrCodes.push(" fs.writeFileSync(imgBasePath, elemshot);");
arrCodes.push("}");
arrCodes.push("let diff = resemble(elemshot).compareTo(imgBasePath).ignoreColors();");
arrCodes.push("let diffResult = await new Promise((resolve) => diff.onComplete(resolve));");
arrCodes.push("diffResult.getDiffImage().pack().pipe(fs.createWriteStream(imgDiffPath));");
arrCodes.push("diffResult.rawMisMatchPercentage");
}
else{
arrCodes.push('await driver.sleep('+expectSleep+').wait(\''+escapeStr(expectPath)+'\', 30000)');
switch(expectType){
case 'text':
arrCodes.push(' .text()');
break;
}
arrCodes.push(' .should.not.be.a(\'error\')');
}
var codeExpectTo = expectTo.replace(/"/g, '\\"').replace(/\n/g, '\\n');
switch(expectCompare){
case 'equal':
arrCodes.push(' .should.equal(_('+(/^(true|false)$/.test(codeExpectTo)?codeExpectTo:'\`'+escapeStr(codeExpectTo)+'\`')+'));');
break;
case 'notEqual':
arrCodes.push(' .should.not.equal(_('+(/^(true|false)$/.test(codeExpectTo)?codeExpectTo:'\`'+escapeStr(codeExpectTo)+'\`')+'));');
break;
case 'contain':
arrCodes.push(' .should.contain(_(\`'+escapeStr(codeExpectTo)+'\`));');
break;
case 'notContain':
arrCodes.push(' .should.not.contain(_(\`'+escapeStr(codeExpectTo)+'\`));');
break;
case 'above':
arrCodes.push(' .should.above('+codeExpectTo+');');
break;
case 'below':
arrCodes.push(' .should.below('+codeExpectTo+');');
break;
case 'match':
arrCodes.push(' .should.match('+escapeStr(codeExpectTo)+');');
break;
case 'notMatch':
arrCodes.push(' .should.not.match('+escapeStr(codeExpectTo)+');');
break;
}
pushTestCode('expect', '', expectType + ', ' + expectPath + ', ' + expectCompare + ', ' + expectTo, arrCodes);
var element, value;
if(expectType === 'count'){
value = yield recorderMobileApp.wait(expectPath, {
timeout: 1000,
noerror: true
}).then(function(elements){
return elements.length;
});
}
else if(expectType === 'imgdiff'){
// 录制时,不需要进行即时的图片校验
value = 0;
}
else{
element = yield recorderMobileApp.sleep(expectSleep).wait(expectPath, 10000);
switch(expectType){
case 'text':
value = yield element.text();
break;
}
value.should.not.be.a('error');
}
switch(expectCompare){
case 'equal':
expectTo = /^(true|false)$/.test(expectTo)?eval(expectTo):eval('\`'+expectTo+'\`');
value.should.equal(getVarStr(expectTo));
break;
case 'notEqual':
expectTo = /^(true|false)$/.test(expectTo)?eval(expectTo):eval('\`'+expectTo+'\`');
value.should.not.equal(getVarStr(expectTo));
break;
case 'contain':
value.should.contain(getVarStr(eval('\`'+expectTo+'\`')));
break;
case 'notContain':
value.should.not.contain(getVarStr(eval('\`'+expectTo+'\`')));
break;
case 'above':
value.should.above(Number(expectTo));
break;
case 'below':
value.should.below(Number(expectTo));
break;
case 'match':
value.should.match(eval(expectTo));
break;
case 'notMatch':
value.should.not.match(eval(expectTo));
break;
}
}).then(doNext).catch(catchError);
break;
// 插入用例
case 'module':
var moduleName = /[\/\\]/.test(data) ? data : commonSpecRelPath + data;
loadModule(moduleName, function(error){
if(error !== null){
catchError(error);
}
else{
console.log(' module'.cyan+': ', moduleName);
arrTestCodes.push('callSpec(\''+escapeStr(moduleName)+'\');\r\n');
doNext();
}
});
break;
}
}
else{
var reDomRequire = /^(val|text|displayed|enabled|selected|attr|css|count|imgdiff)$/;
var reParamRequire = /^(attr|css|cookie|localStorage|sessionStorage|alert)$/;
switch(cmd){
case 'url':
pushTestCode('url', '', data, 'await driver.url(_(\`'+escapeStr(data)+'\`));');
checkerBrowser && checkerBrowser.url(getVarStr(eval('\`'+data+'\`'))).then(doNext).catch(catchError) || doNext();
break;
case 'closeWindow':
pushTestCode('closeWindow', '', '', 'await driver.closeWindow();');
checkerBrowser && checkerBrowser.closeWindow().then(doNext).catch(catchError) || doNext();
break;
case 'sleep':
pushTestCode('sleep', '', data, 'await driver.sleep('+data+');');
checkerBrowser && checkerBrowser.sleep(data).then(doNext).catch(catchError) || doNext();
break;
case 'waitBody':
arrCodes = [];
arrCodes.push('await driver.sleep(500).wait(\'body\', 30000).html().then(function(code){');
arrCodes.push(' isPageError(code).should.be.false;');
arrCodes.push('});');
pushTestCode('waitBody', '', '', arrCodes);
checkerBrowser && checkerBrowser.sleep(500).wait('body', 10000).html().then(function(code){
isPageError(code).should.be.false;
}).then(doNext).catch(catchError) || doNext();
break;
case 'eval':
pushTestCode('eval', '', data.replace(/\n/g, ' \\n '), 'await driver.eval(_(\''+escapeStr(data)+'\'));');
checkerBrowser && checkerBrowser.eval(getVarStr(data)).then(doNext).catch(catchError) || doNext();
break;
case 'mouseMove':
arrCodes = [];
arrCodes.push('await driver.sleep(300).wait(\''+escapeStr(data.path)+'\', 30000)');
arrCodes.push(' .sleep(300).mouseMove('+(data.x ? data.x + ', ' + data.y : '')+');');
pushTestCode('mouseMove', data.text, data.path+(data.x !== undefined?', '+data.x+', '+data.y:''), arrCodes);
checkerBrowser && checkerBrowser.sleep(300).wait(data.path, 10000).sleep(300).mouseMove(data.x, data.y).then(doNext).catch(catchError) || doNext();
break;
case 'mouseDown':
arrCodes = [];
arrCodes.push('await driver.sleep(300).wait(\''+escapeStr(data.path)+'\', 30000)');
arrCodes.push(' .sleep(300).mouseMove('+data.x+', '+data.y+').mouseDown('+data.button+');');
pushTestCode('mouseDown', data.text, data.path + ', ' + data.x + ', ' + data.y + ', ' + data.button, arrCodes);
checkerBrowser && checkerBrowser.sleep(300).wait(data.path, 10000).sleep(300).mouseMove(data.x, data.y).mouseDown(data.button).then(doNext).catch(catchError) || doNext();
break;
case 'mouseUp':
arrCodes = [];
arrCodes.push('await driver.sleep(300).wait(\''+escapeStr(data.path)+'\', 30000)');
arrCodes.push(' .sleep(300).mouseMove('+data.x+', '+data.y+').mouseMove('+data.x+', '+data.y+').mouseUp('+data.button+');');
pushTestCode('mouseUp', data.text, data.path + ', ' + data.x + ', ' + data.y + ', ' + data.button, arrCodes);
checkerBrowser && checkerBrowser.sleep(300).wait(data.path, 10000).sleep(300).mouseMove(data.x, data.y).mouseMove(data.x, data.y).mouseUp(data.button).then(doNext).catch(catchError) || doNext();
break;
case 'click':
arrCodes = [];
var option = data.option;
arrCodes.push('await driver.sleep(300).wait(\''+escapeStr(data.path)+'\', '+(option?'5000':'30000')+')');
arrCodes.push(' .sleep(300).mouseMove('+data.x+', '+data.y+').click('+data.button+')'+(option?'.catch(catchError)':'')+';');
pushTestCode(option?'optionClick':'click', data.text, data.path + ', ' + data.x + ', ' + data.y + ', ' + data.button, arrCodes);
checkerBrowser && checkerBrowser.sleep(300).wait(data.path, 10000).sleep(300).mouseMove(data.x, data.y).click(data.button).then(doNext).catch(catchError) || doNext();
break;
case 'touchClick':
arrCodes = [];
arrCodes.push('await driver.sleep(300).wait(\''+escapeStr(data.path)+'\', 30000)');
arrCodes.push(' .sleep(300).touchClick();');
pushTestCode('touchClick', data.text, data.path, arrCodes);
checkerBrowser && checkerBrowser.sleep(300).wait(data.path, 10000).sleep(300).touchClick().then(doNext).catch(catchError) || doNext();
break;
case 'dblClick':
arrCodes = [];
arrCodes.push('await driver.sleep(300).wait(\''+escapeStr(data.path)+'\', 30000)');
arrCodes.push(' .sleep(300).mouseMove('+data.x+', '+data.y+').click(0).click(0);');
pushTestCode('dblClick', data.text, data.path + ', ' + data.x + ', ' + data.y + ', ' + data.button, arrCodes);
checkerBrowser && checkerBrowser.sleep(300).wait(data.path, 10000).sleep(300).mouseMove(data.x, data.y).click(0).click(0).then(doNext).catch(catchError) || doNext();
break;
case 'sendKeys':
pushTestCode('sendKeys', '', data.keys, 'await driver.sendKeys(\''+escapeStr(data.keys)+'\');');
checkerBrowser && checkerBrowser.sendKeys(data.keys).then(doNext).catch(catchError) || doNext();
break;
case 'keyDown':
pushTestCode('keyDown', '', data.character, 'await driver.keyDown(\''+escapeStr(data.character)+'\');');
checkerBrowser && checkerBrowser.keyDown(data.character).then(doNext).catch(catchError) || doNext();
break;
case 'keyUp':
pushTestCode('keyUp', '', data.character, 'await driver.keyUp(\''+escapeStr(data.character)+'\');');
checkerBrowser && checkerBrowser.keyUp(data.character).then(doNext).catch(catchError) || doNext();
break;
case 'scrollTo':
pushTestCode('scrollTo', '', data.x + ', ' + data.y, 'await driver.scrollTo('+data.x+', '+data.y+');');
checkerBrowser && checkerBrowser.scrollTo(data.x, data.y).then(doNext).catch(catchError) || doNext();
break;
case 'scrollElementTo':
arrCodes = [];
arrCodes.push('await driver.sleep(300).wait(\''+escapeStr(data.path)+'\', 30000)');
arrCodes.push(' .sleep(300).scrollElementTo('+ data.x + ', ' + data.y +');');
pushTestCode('scrollElementTo', data.text, data.path+(data.x !== undefined?', '+data.x+', '+data.y:''), arrCodes);
checkerBrowser && checkerBrowser.sleep(300).wait(data.path, 10000).sleep(300).scrollElementTo(data.x, data.y).then(doNext).catch(catchError) || doNext();
break;
case 'select':
arrCodes = [];
arrCodes.push('await driver.sleep(300).wait(\''+escapeStr(data.path)+'\', 30000)');
arrCodes.push(' .sleep(300).select({');
arrCodes.push(' type: \''+data.type+'\',');
arrCodes.push(' value: \''+data.value+'\'');
arrCodes.push(' });');
pushTestCode('select', data.text, data.path + ', ' + data.type + ', ' + data.value, arrCodes);
checkerBrowser && checkerBrowser.sleep(300).wait(data.path, 10000).sleep(300).select({
type: data.type,
value: data.value
}).then(doNext).catch(catchError) || doNext();
break;
case 'acceptAlert':
pushTestCode('acceptAlert', '', '', 'await driver.acceptAlert();');
checkerBrowser && checkerBrowser.acceptAlert().then(doNext).catch(catchError) || doNext();
break;
case 'dismissAlert':
pushTestCode('dismissAlert', '', '', 'await driver.dismissAlert();');
checkerBrowser && checkerBrowser.dismissAlert().then(doNext).catch(catchError) || doNext();
break;
case 'setAlert':
pushTestCode('setAlert', '', data.text, 'await driver.setAlert("'+data.text+'");');
checkerBrowser && checkerBrowser.setAlert(data.text).then(doNext).catch(catchError) || doNext();
break;
case 'uploadFile':
arrCodes = [];
arrCodes.push('await driver.sleep(300).wait(\''+escapeStr(data.path)+'\', {timeout: 30000, displayed: false})');
arrCodes.push(' .sleep(300).uploadFile(rootPath+\'/uploadfiles/'+data.filename+'\');');
pushTestCode('uploadFile', data.text, data.path + ', ' + data.filename, arrCodes);
checkerBrowser && checkerBrowser.sleep(300).wait(data.path, {timeout: 10000, displayed: false})
.sleep(300).sendElementKeys(rootPath+'/uploadfiles/'+data.filename).then(doNext).catch(catchError) || doNext();
break;
// 添加断言
case 'expect':
co(function*(){
var sleepTime = data.sleep;
var expectType = data.type;
var expectParams = data.params;
var expectCompare = data.compare;
var expectTo = data.to;
arrCodes = [];
if(expectType === 'count'){
arrCodes.push('await driver.sleep('+sleepTime+').wait(\''+escapeStr(expectParams[0])+'\', {timeout: 1000, noerror: true})');
arrCodes.push(' .then(function(elements){');
arrCodes.push(' return elements.length;');
arrCodes.push(' })');
}
else if(expectType === 'imgdiff'){
arrCodes.push("let self = this;");
arrCodes.push("let imgBasePath = self.diffbasePath + '/' + self.caseName + '_' + self.stepId + '.png';");
arrCodes.push("let imgNewPath = self.screenshotPath + '/' + self.caseName + '_' + self.stepId + '_new.png';");
arrCodes.push("let imgDiffPath = self.screenshotPath + '/' + self.caseName + '_' + self.stepId + '_diff.png';");
arrCodes.push("let elemshot = await driver.sleep(300).getScreenshot({");
arrCodes.push(" elem: '"+escapeStr(expectParams[0])+"',");
arrCodes.push(" filename: imgNewPath");
arrCodes.push("});");
arrCodes.push("elemshot = new Buffer(elemshot, 'base64');");
arrCodes.push("if(!fs.existsSync(imgBasePath) || process.env['npm_config_rebuilddiff']){");
arrCodes.push(" fs.writeFileSync(imgBasePath, elemshot);");
arrCodes.push("}");
arrCodes.push("let diff = resemble(elemshot).compareTo(imgBasePath).ignoreColors();");
arrCodes.push("let diffResult = await new Promise((resolve) => diff.onComplete(resolve));");
arrCodes.push("diffResult.getDiffImage().pack().pipe(fs.createWriteStream(imgDiffPath));");
arrCodes.push("diffResult.rawMisMatchPercentage");
}
else{
if(reDomRequire.test(expectType)){
arrCodes.push('await driver.sleep('+sleepTime+').wait(\''+escapeStr(expectParams[0])+'\', 30000)');
}
else{
arrCodes.push('await driver');
}
switch(expectType){
case 'val':
arrCodes.push(' .val()');
break;
case 'text':
arrCodes.push(' .text()');
break;
case 'displayed':
arrCodes.push(' .displayed()');
break;
case 'enabled':
arrCodes.push(' .enabled()');
break;
case 'selected':
arrCodes.push(' .selected()');
break;
case 'attr':
arrCodes.push(' .attr(\''+escapeStr(expectParams[1])+'\')');
break;
case 'css':
arrCodes.push(' .css(\''+escapeStr(expectParams[1])+'\')');
break;
case 'url':
arrCodes.push(' .url()');
break;
case 'title':
arrCodes.push(' .title()');
break;
case 'cookie':
arrCodes.push(' .cookie(\''+escapeStr(expectParams[0])+'\')');
break;
case 'localStorage':
arrCodes.push(' .localStorage(\''+escapeStr(expectParams[0])+'\')');
break;
case 'sessionStorage':
arrCodes.push(' .sessionStorage(\''+escapeStr(expectParams[0])+'\')');
break;
case 'alert':
arrCodes.push(' .getAlert()');
break;
case 'jscode':
arrCodes.push(' .eval(\''+escapeStr(expectParams[0])+'\')');
break;
}
arrCodes.push(' .should.not.be.a(\'error\')');
}
var codeExpectTo = expectTo.replace(/"/g, '\\"').replace(/\n/g, '\\n');
switch(expectCompare){
case 'equal':
arrCodes.push(' .should.equal(_('+(/^(true|false)$/.test(codeExpectTo)?codeExpectTo:'\`'+escapeStr(codeExpectTo)+'\`')+'));');
break;
case 'notEqual':
arrCodes.push(' .should.not.equal(_('+(/^(true|false)$/.test(codeExpectTo)?codeExpectTo:'\`'+escapeStr(codeExpectTo)+'\`')+'));');
break;
case 'contain':
arrCodes.push(' .should.contain(_(\`'+escapeStr(codeExpectTo)+'\`));');
break;
case 'notContain':
arrCodes.push(' .should.not.contain(_(\`'+escapeStr(codeExpectTo)+'\`));');
break;
case 'above':
arrCodes.push(' .should.above('+codeExpectTo+');');
break;
case 'below':
a