blob: 197858f4c5c79538cf063520c04ee9f25dd9d5fe [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
'use strict'
var path = require('path');
var os = require('os')
var fs = require('fs')
const BlinkDiff = require('blink-diff');
var platform = process.env.platform || 'android';
const servePort = process.env.serport || 12581
platform = platform.toLowerCase();
var browser = process.env.browser || '';
const isIOS = platform === 'ios';
const isRunInCI = process.env.run_in_ci?true:false;
var iOSOpts = {
deviceName: 'iPhone 6',
target: 'ios',
platformName: 'iOS',
slowEnv: isRunInCI,
autoAcceptAlerts:false,
app: path.join(__dirname, '..', '../ios/playground/build/Debug-iphonesimulator/WeexDemo.app')
};
var androidOpts = {
platformName: 'Android',
target: 'android',
slowEnv: isRunInCI,
autoAcceptAlerts:false,
app: path.join(__dirname, '..', '../android/playground/app/build/outputs/apk/playground-debug.apk')
};
var androidChromeOpts = {
platformName: 'Android',
target: 'web',
browserName: 'Chrome'
};
if(isRunInCI){
console.log("Running in CI Envirment");
}
function getIpAddress(){
let ifs = os.networkInterfaces()
let addresses = ['127.0.0.1'];
for( var i in ifs){
let interfaces = ifs[i];
interfaces.forEach((face)=>{
if(!face.internal && face.family == 'IPv4'){
addresses.unshift(face.address);
}
})
}
return addresses[0];
}
function diffImage(imageAPath, imageB, threshold, outputPath) {
if (!fs.existsSync(imageAPath)) {
fs.writeFileSync(imageAPath, imageB, 'base64', function(err) {
console.log(err);
});
}
return new Promise((resolve, reject) => {
var diff = new BlinkDiff({
imageAPath: imageAPath, // Path
imageB: imageB, // Buffer
thresholdType: BlinkDiff.THRESHOLD_PIXEL,
threshold: threshold,
imageOutputPath: outputPath,
cropImageA:isIOS?{y:128}:{y:242,height:1530},//android: 242 - status bar(72)+navigator bar(170)
cropImageB:isIOS?{y:128}:{y:242,height:1530}
});
diff.run((err, result) => {
if (err) {
return reject(err);
}
var ifPassed = diff.hasPassed(result.code);
console.log(ifPassed ? 'Image Comparison Passed' : 'Image Comparison Failed');
console.log(`Found ${result.differences} pixel differences between two images.`);
resolve(ifPassed);
});
});
}
module.exports = {
isIos:function(){
return isIOS;
},
getConfig:function(){
if(browser){
return androidChromeOpts;
}
return isIOS? iOSOpts : androidOpts;
},
getDeviceHost:function(){
return getIpAddress()+":12581";
},
getPage:function(name){
let url
if(browser){
url = 'http://'+ getIpAddress()+':'+servePort+'/vue.html?page=/test/build-web'+name
}else{
url = 'wxpage://' + getIpAddress()+":"+servePort+"/test/build"+name;
}
console.log(url)
return url
},
getTimeoutMills:function(){
return ( isRunInCI ? 60 : 10 ) * 60 * 1000;
},
getGETActionWaitTimeMills:function(){
return (isRunInCI ? 120 : 5 ) * 1000;
},
diffImage,
createDriver:function(wd){
var driver = global._wxDriver;
if(!driver){
console.log('Create new driver');
let driverFactory = wd(this.getConfig())
driverFactory.addPromiseChainMethod('dragUpAndDown',function(){
return this
.getWindowSize()
.then(size=>{
let middleX = size.width * 0.5
return this
.touch('drag', {fromX:middleX, fromY:size.height*0.7, toX:middleX, toY: size.height*0.3, duration: 1})
.sleep(1000)
.touch('drag', {fromX:middleX, fromY:size.height*0.3, toX:middleX, toY: size.height*0.7, duration: 1})
.sleep(1000)
})
})
driverFactory.addPromiseChainMethod('dragUp',function(distance){
return this
.getWindowSize()
.then(size=>{
let middleX = size.width * 0.5
let startY = size.height * 0.3
return this
.touch('drag', {fromX:middleX, fromY:startY+distance, toX:middleX, toY: startY, duration: 1})
.sleep(1000)
})
})
//direct : toUp,toDown,toLeft,toRight, dragStartPct: 偏移量,0~1
driverFactory.addPromiseChainMethod('drag', function(direct,dragStartPct) {
return this.getWindowSize()
.then(size => {
let {width,height} = size;
if(!direct){direct='toUp';}if(!dragStartPct){dragStartPct=0;}
let fromX,toX,fromY,toY;
switch (direct) {
case 'toUp':
fromX = toX = Math.floor(width / 2);
fromY = Math.floor(height * 1 / 4 + height * dragStartPct * 3/4);
toY = Math.floor(height * 3 / 4 + height * dragStartPct * 1/4);
break;
case 'toLeft':
fromY = toY = Math.floor(height / 2);
fromX = Math.floor(width * 1 / 4 + width * dragStartPct * 3 / 4);
toX = Math.floor(width * 3 / 4 + width * dragStartPct * 1 / 4);
break;
case 'toRight':
fromY = toY = Math.floor(height / 2);
toX = Math.floor(width * 1 / 4 + width * dragStartPct * 3 / 4);
fromX = Math.floor(width * 3 / 4 + width * dragStartPct * 1 / 4);
break;
case 'toDown':
default:
fromX = toX = Math.floor(width / 2);
toY = Math.floor(height * 1 / 4 + height * dragStartPct * 3/4);
fromY = Math.floor(height * 3 / 4 + height * dragStartPct * 1/4);
break;
}
return this.touch('drag', {
fromX: fromX,fromY: fromY,toX: toX,toY: toY,duration: 0.1
})
.sleep(500)
})
});
driverFactory.addPromiseChainMethod('swipeLeft', function (distanceRatio, yRatio) {
return this
.getWindowSize()
.then(size => {
let y = yRatio * size.height;
let startX = size.width * 0.8;
let endX = startX - size.width * distanceRatio;
return this
.touch('drag', {fromX: startX, toX: endX, fromY: y, toY: y, duration: 1})
.sleep(1000)
})
})
driverFactory.addPromiseChainMethod('swipeRight', function (distanceRatio, yRatio) {
return this
.getWindowSize()
.then(size => {
let y = yRatio * size.height;
let startX = size.width * 0.2;
let endX = startX + size.width * distanceRatio;
return this
.touch('drag', {fromX: startX, toX: endX, fromY: y, toY: y, duration: 1})
.sleep(1000)
})
})
driverFactory.addPromiseChainMethod('saveShot', function(filepath){
return this.takeScreenshot()
.then(imgData => {
var newImg = new Buffer(imgData, 'base64');
fs.writeFileSync(filepath, newImg);
return this;
})
});
driverFactory.addPromiseChainMethod('clickScreenById', function(id,index) {
if(!index)index = 0;
return this.elementsById(id)
.then((array)=>{
if(array){
if(index<0)index=0;
if(index>=array.length)index=array.length-1;
return array[index].getRect()
.then(rect => {
var left = rect.x;
var top = rect.y;
var width = rect.width;
var height = rect.height;
var touchX = Math.floor(left + width / 2);
var touchY = Math.floor(top + height / 2);
console.log('rect:' + touchX + " " + touchY);
return this
.touch('tap', {
x: touchX,
y: touchY
})
.sleep(500)
})
}else{
console.log('id='+id+'的元素不存在!')
return this;
}
})
});
driver = driverFactory.initPromiseChain();
driver.configureHttp({
timeout: 100000
});
global._wxDriver = driver;
}
return driver;
},
init:function(driver){
if(driver._isInit)
return driver.status()
else{
driver._isInit = true;
return driver.initDriver().sleep(20000) //ios cannot detect at once
}
},
quit:function(driver){
if(browser)
return driver.quit()
var filepath = path.resolve(__dirname,'../../last.png');
return driver.saveShot(filepath).sleep(1000).back().sleep(1000);
},
quitWithoutBack:function(driver){
if(browser)
return driver.quit()
var filepath = path.resolve(__dirname,'../../last.png');
return driver.saveShot(filepath).sleep(1000);
}
}