Merge pull request #4 from wodka/features/security_updates

improve security
This commit is contained in:
Michael Schramm 2019-07-15 21:07:08 +02:00 committed by GitHub
commit 6d75c011a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 8378 additions and 4110 deletions

View File

@ -23,8 +23,7 @@ var smtpTransport = nodemailer.createTransport(config.mailer.options);
*/
exports.deleteSubmissions = function(req, res) {
var submission_id_list = req.body.deleted_submissions,
form = req.form;
var submission_id_list = req.body.deleted_submissions;
FormSubmission.remove({ form: req.form, _id: {$in: submission_id_list} }, function(err){
@ -121,9 +120,7 @@ exports.createSubmission = function(req, res) {
* Get List of Submissions for a given Form
*/
exports.listSubmissions = function(req, res) {
var _form = req.form;
FormSubmission.find({ form: _form._id }).sort('created').lean().exec(function(err, _submissions) {
FormSubmission.find({ form: req.form._id }).sort('created').lean().exec(function(err, _submissions) {
if (err) {
console.error(err);
return res.status(500).send({
@ -357,11 +354,10 @@ var readForRender = exports.readForRender = function(req, res) {
* Update a form
*/
exports.update = function(req, res) {
var form = req.form;
var updatedForm = req.body.form;
if(!form.analytics && req.body.form.analytics){
if(!form.analytics){
form.analytics = {
visitors: [],
gaCode: ''
@ -376,7 +372,7 @@ exports.update = function(req, res) {
});
} else {
if(!updatedForm){
res.status(400).send({
return res.status(400).send({
message: 'Updated Form is empty'
});
}
@ -426,7 +422,9 @@ exports.delete = function(req, res) {
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(form);
res.json(
helpers.removeSensitiveModelData('private_form', form)
);
}
});
};
@ -513,8 +511,7 @@ exports.formByID = function(req, res, next, id) {
});
}
else {
//Remove sensitive information from User object
req.form = helpers.removeSensitiveModelData('private_form', form.toJSON());
req.form = form;
return next();
}
});
@ -542,7 +539,7 @@ exports.formByIDFast = function(req, res, next, id) {
}
else {
//Remove sensitive information from User object
req.form = helpers.removeSensitiveModelData('public_form', form);
req.form = form;
return next();
}
});
@ -555,7 +552,7 @@ exports.formByIDFast = function(req, res, next, id) {
*/
exports.hasAuthorization = function(req, res, next) {
var form = req.form;
if (req.form.admin.id !== req.user.id && req.user.roles.indexOf('admin') < 0) {
if (!req.form.admin || req.form.admin.id !== req.user.id && req.user.roles.indexOf('admin') < 0) {
return res.status(403).send({
message: 'User '+req.user.username+' is not authorized to edit Form: '+form.title
});

View File

@ -11,7 +11,7 @@ var validFormats = ['combined', 'common', 'dev', 'short', 'tiny'];
// Instantiating the default winston application logger with the Console
// transport
var logger = new winston.Logger({
var logger = new winston.createLogger({
transports: [
new winston.transports.Console({
level: 'info',
@ -49,7 +49,7 @@ logger.setupFileLogger = function setupFileLogger() {
// Check first if the configured path is writable and only then
// instantiate the file logging transport
if (fs.openSync(fileLoggerTransport.filename, 'a+')) {
logger.add(winston.transports.File, fileLoggerTransport);
logger.add(new winston.transports.File(), fileLoggerTransport);
}
return true;
@ -74,7 +74,7 @@ logger.getLogOptions = function getLogOptions() {
var _config = _.clone(config, true);
var configFileLogger = _config.log.fileLogger;
if (process.env.NODE_ENV !== 'test' && !_.has(_config, 'log.fileLogger.directoryPath') || !_.has(_config, 'log.fileLogger.fileName')) {
console.log('unable to find logging file configuration');
return false;
@ -120,13 +120,13 @@ logger.getMorganOptions = function getMorganOptions() {
logger.getLogFormat = function getLogFormat() {
var format = config.log && config.log.format ? config.log.format.toString() : 'combined';
if (!_.includes(validFormats, format)) {
if (!_.includes(validFormats, format)) {
if (process.env.NODE_ENV !== 'test') {
console.log();
console.log(chalk.yellow('Warning: An invalid format was provided. The logger will use the default format of "' + format + '"'));
console.log();
}
}
}
return format;
};

11804
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -21,98 +21,98 @@
"init": "node scripts/setup.js"
},
"dependencies": {
"async": "^1.4.2",
"async": "^2.6.3",
"body-parser": "^1.19.0",
"bower": "^1.8.8",
"chalk": "^1.1.3",
"chalk": "^2.4.2",
"compression": "^1.7.4",
"connect": "^3.4.1",
"connect-mongo": "^2.0.0",
"connect": "^3.7.0",
"connect-mongo": "^3.0.0",
"consolidate": "~0.14.5",
"cookie-parser": "~1.4.0",
"deep-diff": "^0.3.4",
"dotenv": "^2.0.0",
"cookie-parser": "^1.4.4",
"deep-diff": "^1.0.2",
"dotenv": "^8.0.0",
"email-verification": "github:tellform/node-email-verification",
"envfile": "^2.1.1",
"express": "^4.16.4",
"express-session": "^1.16.1",
"glob": "^7.0.3",
"grunt": "~0.4.1",
"grunt-concurrent": "~2.3.0",
"grunt-contrib-csslint": "~1.0.0",
"grunt-contrib-cssmin": "~1.0.1",
"grunt-contrib-jshint": "~1.0.0",
"grunt-contrib-uglify": "~0.11.0",
"grunt-env": "~0.4.1",
"express": "^4.17.1",
"express-session": "^1.16.2",
"glob": "^7.1.4",
"grunt": "^1.0.4",
"grunt-concurrent": "^3.0.0",
"grunt-contrib-csslint": "^2.0.0",
"grunt-contrib-cssmin": "^3.0.0",
"grunt-contrib-jshint": "^2.1.0",
"grunt-contrib-uglify": "^4.0.1",
"grunt-env": "^0.4.4",
"grunt-html2js": "^0.6.0",
"grunt-ng-annotate": "~1.0.1",
"helmet": "^3.16.0",
"grunt-ng-annotate": "^3.0.0",
"helmet": "^3.18.0",
"i18n": "^0.8.3",
"jit-grunt": "^0.9.1",
"jsdom": "^15.1.1",
"lodash": "^4.17.13",
"lodash": "^4.17.14",
"main-bower-files": "^2.13.1",
"method-override": "~2.3.0",
"method-override": "^3.0.0",
"mkdirp": "^0.5.1",
"mongoose": "^5.6.4",
"morgan": "^1.9.1",
"nodemailer": "~4.0.0",
"passport": "~0.3.0",
"nodemailer": "^6.3.0",
"passport": "^0.4.0",
"passport-anonymous": "^1.0.1",
"passport-local": "~1.0.0",
"passport-localapikey-update": "^0.5.0",
"path-exists": "^2.1.0",
"passport-local": "^1.0.0",
"passport-localapikey-update": "^0.6.0",
"path-exists": "^4.0.0",
"prerender-node": "^2.2.1",
"pug": "^2.0.3",
"pug": "^2.0.4",
"random-js": "^1.0.8",
"raven": "^0.9.0",
"request": "^2.88.0",
"socket.io": "^1.4.6",
"socket.io-redis": "^1.0.0",
"swig": "~1.4.1",
"uuid-token-generator": "^0.5.0",
"winston": "^2.3.1"
"socket.io": "^1.7.4",
"socket.io-redis": "^5.2.0",
"swig": "^1.4.2",
"uuid-token-generator": "^1.0.0",
"winston": "^3.2.1"
},
"devDependencies": {
"all-contributors-cli": "^4.3.0",
"chromedriver": "^2.25.1",
"coveralls": "^2.11.4",
"cross-spawn": "^5.0.0",
"del": "^2.2.2",
"grunt-cli": "~0.1.13",
"grunt-closure-compiler": "0.0.21",
"all-contributors-cli": "^6.7.0",
"chromedriver": "^75.1.0",
"coveralls": "^3.0.5",
"cross-spawn": "^6.0.5",
"del": "^5.0.0",
"grunt-cli": "^1.3.2",
"grunt-closure-compiler": "^0.0.21",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-uglify": "^0.11.1",
"grunt-contrib-watch": "~0.6.1",
"grunt-contrib-uglify": "^4.0.1",
"grunt-contrib-watch": "^1.1.0",
"grunt-execute": "^0.2.2",
"grunt-i18nlint": "github:jwarby/grunt-i18nlint",
"grunt-karma": "~0.12.1",
"grunt-mocha-istanbul": "^3.0.1",
"grunt-mocha-test": "~0.12.1",
"grunt-newer": "~1.1.1",
"grunt-nodemon": "~0.4.0",
"grunt-karma": "^3.0.2",
"grunt-mocha-istanbul": "^5.0.2",
"grunt-mocha-test": "^0.13.3",
"grunt-newer": "^1.3.0",
"grunt-nodemon": "^0.4.2",
"grunt-usemin": "^3.1.1",
"grunt-wiredep": "^3.0.1",
"istanbul": "^0.4.0",
"jasmine-core": "^2.4.1",
"karma": "~0.13.14",
"karma-chrome-launcher": "~0.2.1",
"karma-coverage": "~0.5.3",
"karma-firefox-launcher": "~0.1.7",
"karma-jasmine": "^0.3.6",
"karma-jasmine-html-reporter": "^0.1.8",
"karma-mocha-reporter": "^1.1.1",
"karma-ng-html2js-preprocessor": "^0.2.0",
"istanbul": "^0.4.5",
"jasmine-core": "^3.4.0",
"karma": "^4.2.0",
"karma-chrome-launcher": "^3.0.0",
"karma-coverage": "^1.1.2",
"karma-firefox-launcher": "^1.1.0",
"karma-jasmine": "^2.0.1",
"karma-jasmine-html-reporter": "^1.4.2",
"karma-mocha-reporter": "^2.2.5",
"karma-ng-html2js-preprocessor": "^1.0.0",
"karma-phantomjs-launcher": "^1.0.4",
"mocha": "^3.1.2",
"mocha-lcov-reporter": "^1.0.0",
"nightwatch": "^0.9.8",
"phantomjs": "^1.9.18",
"selenium-server": "^3.0.1",
"should": "~7.1.1",
"supertest": "~1.2.0",
"supertest-session": "~2.0.1",
"mocha": "^6.1.4",
"mocha-lcov-reporter": "^1.3.0",
"nightwatch": "^1.1.13",
"phantomjs": "^2.1.7",
"selenium-server": "^3.141.59",
"should": "^13.2.3",
"supertest": "^4.0.2",
"supertest-session": "^4.0.0",
"wiredep": "^4.0.0"
}
}

View File

@ -1,17 +0,0 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
# Apply for all files
[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

9
selenium/.gitignore vendored
View File

@ -1,9 +0,0 @@
.DS_Store
.idea
node_modules
npm-debug.log
uirecorder.log
reports
screenshots/**/*.png
screenshots/**/*.html
screenshots/**/*.json

View File

@ -1,27 +0,0 @@
{
// Use IntelliSense to learn about possible Node.js debug attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug UIRecorder Local",
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
"cwd": "${workspaceRoot}",
"args": ["--reporter", "mochawesome-uirecorder", "${file}"],
"env": {
"webdriver": "127.0.0.1"
}
},
{
"type": "node",
"request": "launch",
"name": "Debug UIRecorder Default",
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
"cwd": "${workspaceRoot}",
"args": ["--reporter", "mochawesome-uirecorder", "${file}"]
}
]
}

View File

@ -1,28 +0,0 @@
UI Recorder test sample project
================
It's a UI Recorder test sample project.
Save your test code here.
Get more info: [http://uirecorder.com/](http://uirecorder.com/)
How to run test case?
================
1. npm install
2. source run.sh ( Linux|Mac ) or run.bat ( Windows )
How to dock jenkins?
================
1. Add commands
source ./install.sh
source ./run.sh
2. Add reports
> JUnit: reports/index.xml
> HTML: reports/

View File

@ -1 +0,0 @@
Please save common test case here.

View File

@ -1,23 +0,0 @@
{
"webdriver": {
"host": "127.0.0.1",
"port": "4444",
"browsers": "chrome"
},
"vars": {
"LoginUsername": "root",
"LoginPassword": "root",
"ShortTextTitle": "SeleniumShortText",
"Profile_NewFirstName": "SeleniumUser_FirstName",
"Profile_NewLastName": "SeleniumUser_LastName",
"Profile_OldFirstName": "Admin",
"Profile_OldLastName": "Account",
"Profile_NewInvalidEmail": "SeleniumInvalidEmail"
},
"recorder": {
"pathAttrs": "data-id,data-name,type,data-type,role,data-role,data-value",
"attrValueBlack": "",
"classValueBlack": "",
"hideBeforeExpect": ""
}
}

View File

View File

@ -1,4 +0,0 @@
ls ~/nvm || git clone https://github.com/creationix/nvm.git ~/nvm
source ~/nvm/nvm.sh
nvm install v7.10.0
npm install

View File

@ -1,24 +0,0 @@
{
"name": "uirecorderTest",
"version": "1.0.0",
"description": "",
"main": "",
"dependencies": {
"chai": "3.5.0",
"jwebdriver": "2.2.4",
"mocha": "3.1.2",
"mocha-parallel-tests": "1.2.4",
"mochawesome-uirecorder": "1.5.22",
"resemblejs-node": "1.0.0",
"selenium-standalone": "6.x.x"
},
"devDependencies": {},
"scripts": {
"installdriver": "./node_modules/.bin/selenium-standalone install --drivers.firefox.baseURL=http://npm.taobao.org/mirrors/geckodriver --baseURL=http://npm.taobao.org/mirrors/selenium --drivers.chrome.baseURL=http://npm.taobao.org/mirrors/chromedriver --drivers.ie.baseURL=http://npm.taobao.org/mirrors/selenium",
"server": "./node_modules/.bin/selenium-standalone start",
"test": "./node_modules/.bin/mocha \"*/**/*.spec.js\" --reporter mochawesome-uirecorder --bail",
"singletest": "./node_modules/.bin/mocha --reporter mochawesome-uirecorder --bail",
"paralleltest": "./node_modules/.bin/mocha-parallel-tests \"*/**/*.spec.js\" --reporter mochawesome-uirecorder --max-parallel 5 --bail"
},
"author": ""
}

View File

@ -1,7 +0,0 @@
@echo off
if "%1" neq "" (
npm run singletest %1 %2
) else (
npm run paralleltest
)

View File

@ -1,5 +0,0 @@
if [ "$1" = "" ]; then
npm run paralleltest
else
npm run singletest $1 $2
fi

View File

@ -1,378 +0,0 @@
const fs = require('fs');
const path = require('path');
const chai = require("chai");
const should = chai.should();
const JWebDriver = require('jwebdriver');
chai.use(JWebDriver.chaiSupportChainPromise);
const resemble = require('resemblejs-node');
resemble.outputSettings({
errorType: 'flatDifferenceIntensity'
});
const rootPath = getRootPath();
module.exports = function(){
let driver, testVars;
before(function(){
let self = this;
driver = self.driver;
testVars = self.testVars;
});
it('url: http://localhost:5000', async function(){
await driver.url(_(`http://localhost:5000`));
});
it('waitBody: ', async function(){
await driver.sleep(500).wait('body', 30000).html().then(function(code){
isPageError(code).should.be.false;
});
});
it('insertVar: username ( #username, {{LoginUsername}} )', async function(){
await driver.sleep(300).wait('#username', 30000)
.val(_(`{{LoginUsername}}`));
});
it('insertVar: password ( #password, {{LoginUsername}} )', async function(){
await driver.sleep(300).wait('#password', 30000)
.val(_(`{{LoginUsername}}`));
});
it('expect: displayed, .btn-signup, equal, true', async function(){
await driver.sleep(300).wait('.btn-signup', 30000)
.displayed()
.should.not.be.a('error')
.should.equal(_(true));
});
it('click: Sign in ( button, 174, 18, 0 )', async function(){
await driver.sleep(300).wait('button.btn-signup', 30000)
.sleep(300).click();
});
it('expect: displayed, div.new-button, equal, true', async function(){
await driver.sleep(300).wait('div.new-button', 30000)
.displayed()
.should.not.be.a('error')
.should.equal(_(true));
});
it('expect: displayed, a.dropdown-toggle, equal, true', async function(){
await driver.sleep(300).wait('a.dropdown-toggle', 30000)
.displayed()
.should.not.be.a('error')
.should.equal(_(true));
});
it('click: My Settings ( a.dropdown-toggle )', async function(){
await driver.sleep(300).wait('a.dropdown-toggle', 30000)
.sleep(300).click();
});
it('× expect: display, ul.dropdown-menu > li:nth-child(1) > a.ng-binding, equal, true', async function(){
await driver.sleep(300).wait('ul.dropdown-menu > li:nth-child(1) > a.ng-binding', 30000)
.displayed()
.should.not.be.a('error')
.should.equal(_(true));
});
it('× expect: display, ul.dropdown-menu > li:nth-child(3) > a.ng-binding, equal, true', async function(){
await driver.sleep(300).wait('ul.dropdown-menu > li:nth-child(3) > a.ng-binding', 30000)
.displayed()
.should.not.be.a('error')
.should.equal(_(true));
});
it('click: Edit Profile ( ul.dropdown-menu > li:nth-child(1) > a.ng-binding )', async function(){
await driver.sleep(300).wait('ul.dropdown-menu > li:nth-child(1) > a.ng-binding', 30000)
.sleep(300).click();
});
it('waitBody: ', async function(){
await driver.sleep(500).wait('body', 30000).html().then(function(code){
isPageError(code).should.be.false;
});
});
it('× insertVar: firstName ( #firstName, {{Profile_NewFirstName}} )', async function(){
await driver.sleep(300).wait('#firstName', 30000)
.val(_(`{{Profile_NewFirstName}}`));
});
it('× insertVar: lastName ( #lastName, {{Profile_NewLastName}} )', async function(){
await driver.sleep(300).wait('#lastName', 30000)
.val(_(`{{Profile_NewLastName}}`));
});
it('× click: Save Changes ( button.btn-signup )', async function(){
await driver.sleep(300).wait('button.btn-signup', 30000)
.sleep(300).click();
});
it('× expect: displayed, div.text-success, equal, true', async function(){
await driver.sleep(300).wait('div.text-success', 30000)
.displayed()
.should.not.be.a('error')
.should.equal(_(true));
});
it('× expect: displayed, .text-danger, notEqual, true', async function(){
await driver.sleep(300).wait('.text-danger', 300)
.displayed()
.should.not.be.a('error')
.should.not.equal(_(true));
});
/*
** Revert back to expected names
*/
it('× insertVar: firstName ( #firstName, {{Profile_OldFirstName}} )', async function(){
await driver.sleep(300).wait('#firstName', 30000)
.val(_(`{{Profile_OldFirstName}}`));
});
it('× insertVar: lastName ( #lastName, {{Profile_OldLastName}} )', async function(){
await driver.sleep(300).wait('#lastName', 30000)
.val(_(`{{Profile_OldLastName}}`));
});
it('× click: Save Changes ( button.btn-signup, 95, 10, 0 )', async function(){
await driver.sleep(300).wait('button.btn-signup', 30000)
.sleep(300).click();
});
it('× expect: displayed, .text-danger, notEqual, true', async function(){
await driver.sleep(300).wait('.text-danger', 300)
.displayed()
.should.not.be.a('error')
.should.not.equal(_(true));
});
//Check that we can't save an invalid email
it('× insertVar: email ( #email, {{Profile_NewInvalidEmail}} )', async function(){
await driver.sleep(300).wait('#email', 30000)
.val(_(`{{Profile_NewInvalidEmail}}`));
});
it('× click: Save Changes ( button.btn-signup )', async function(){
await driver.sleep(300).wait('button.btn-signup', 30000)
.sleep(300).click();
});
it('url: http://localhost:5000/#!/settings/profile', async function(){
await driver.url(_(`http://localhost:5000/#!/settings/profile`));
});
it('waitBody: ', async function(){
await driver.sleep(500).wait('body', 30000).html().then(function(code){
isPageError(code).should.be.false;
});
});
it('expect: text, #email, notEqual, {{Profile_NewInvalidEmail}}', async function(){
await driver.sleep(300).wait('#email', 300)
.text()
.should.not.be.a('error')
.should.not.equal(_(`{{Profile_NewInvalidEmail}}`));
});
/*
** Logout
*/
it('click: Signout ( //a[text()="Signout"], 31, 31, 0 )', async function(){
await driver.sleep(300).wait('//a[text()="Signout"]', 30000)
.sleep(300).mouseMove(31, 31).click(0);
});
it('expect: displayed, button.btn-signup, equal, true', async function(){
await driver.sleep(300).wait('button.btn-signup', 30000)
.displayed()
.should.not.be.a('error')
.should.equal(_(true));
});
function _(str){
if(typeof str === 'string'){
return str.replace(/\{\{(.+?)\}\}/g, function(all, key){
return testVars[key] || '';
});
}
else{
return str;
}
}
};
if(module.parent && /mocha\.js/.test(module.parent.id)){
runThisSpec();
}
function runThisSpec(){
// read config
let webdriver = process.env['webdriver'] || '';
let proxy = process.env['wdproxy'] || '';
let config = require(rootPath + '/config.json');
let webdriverConfig = Object.assign({},config.webdriver);
let host = webdriverConfig.host;
let port = webdriverConfig.port || 4444;
let match = webdriver.match(/([^\:]+)(?:\:(\d+))?/);
if(match){
host = match[1] || host;
port = match[2] || port;
}
let testVars = config.vars;
let browsers = webdriverConfig.browsers;
browsers = browsers.replace(/^\s+|\s+$/g, '');
delete webdriverConfig.host;
delete webdriverConfig.port;
delete webdriverConfig.browsers;
// read hosts
let hostsPath = rootPath + '/hosts';
let hosts = '';
if(fs.existsSync(hostsPath)){
hosts = fs.readFileSync(hostsPath).toString();
}
let specName = path.relative(rootPath, __filename).replace(/\\/g,'/').replace(/\.js$/,'');
browsers.split(/\s*,\s*/).forEach(function(browserName){
let caseName = specName + ' : ' + browserName;
let browserInfo = browserName.split(' ');
browserName = browserInfo[0];
let browserVersion = browserInfo[1];
describe(caseName, function(){
this.timeout(600000);
this.slow(1000);
let driver;
before(function(){
let self = this;
let driver = new JWebDriver({
'host': host,
'port': port
});
let sessionConfig = Object.assign({}, webdriverConfig, {
'browserName': browserName,
'version': browserVersion,
'ie.ensureCleanSession': true,
'chromeOptions': {
'args': ['--enable-automation']
}
});
if(proxy){
sessionConfig.proxy = {
'proxyType': 'manual',
'httpProxy': proxy,
'sslProxy': proxy
}
}
else if(hosts){
sessionConfig.hosts = hosts;
}
self.driver = driver.session(sessionConfig).maximize().config({
pageloadTimeout: 30000, // page onload timeout
scriptTimeout: 5000, // sync script timeout
asyncScriptTimeout: 10000 // async script timeout
});
self.testVars = testVars;
let casePath = path.dirname(caseName);
self.screenshotPath = rootPath + '/screenshots/' + casePath;
self.diffbasePath = rootPath + '/diffbase/' + casePath;
self.caseName = caseName.replace(/.*\//g, '').replace(/\s*[:\.\:\-\s]\s*/g, '_');
mkdirs(self.screenshotPath);
mkdirs(self.diffbasePath);
self.stepId = 0;
return self.driver;
});
module.exports();
beforeEach(function(){
let self = this;
self.stepId ++;
if(self.skipAll){
self.skip();
}
});
afterEach(async function(){
let self = this;
let currentTest = self.currentTest;
let title = currentTest.title;
if(currentTest.state === 'failed' && /^(url|waitBody|switchWindow|switchFrame):/.test(title)){
self.skipAll = true;
}
if(!/^(closeWindow):/.test(title)){
let filepath = self.screenshotPath + '/' + self.caseName + '_' + self.stepId;
let driver = self.driver;
try{
// catch error when get alert msg
await driver.getScreenshot(filepath + '.png');
let url = await driver.url();
let html = await driver.source();
html = '<!--url: '+url+' -->\n' + html;
fs.writeFileSync(filepath + '.html', html);
let cookies = await driver.cookies();
fs.writeFileSync(filepath + '.cookie', JSON.stringify(cookies));
}
catch(e){}
}
});
after(function(){
return this.driver.close();
});
});
});
}
function getRootPath(){
let rootPath = path.resolve(__dirname);
while(rootPath){
if(fs.existsSync(rootPath + '/config.json')){
break;
}
rootPath = rootPath.substring(0, rootPath.lastIndexOf(path.sep));
}
return rootPath;
}
function mkdirs(dirname){
if(fs.existsSync(dirname)){
return true;
}else{
if(mkdirs(path.dirname(dirname))){
fs.mkdirSync(dirname);
return true;
}
}
}
function callSpec(name){
try{
require(rootPath + '/' + name)();
}
catch(e){
console.log(e)
process.exit(1);
}
}
function isPageError(code){
return code == '' || / jscontent="errorCode" jstcache="\d+"|diagnoseConnectionAndRefresh|dnserror_unavailable_header|id="reportCertificateErrorRetry"|400 Bad Request|403 Forbidden|404 Not Found|500 Internal Server Error|502 Bad Gateway|503 Service Temporarily Unavailable|504 Gateway Time-out/i.test(code);
}
function catchError(error){
}