forked from enviPath/enviPy
Current Dev State
This commit is contained in:
60
static/js/ketcher2/test/utils/browser-session.js
Normal file
60
static/js/ketcher2/test/utils/browser-session.js
Normal file
@ -0,0 +1,60 @@
|
||||
/****************************************************************************
|
||||
* Copyright 2017 EPAM Systems
|
||||
*
|
||||
* Licensed 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.
|
||||
***************************************************************************/
|
||||
|
||||
/* eslint-env node */
|
||||
|
||||
var webdriverio = require('webdriverio');
|
||||
var chromedriver = require('chromedriver');
|
||||
|
||||
var path = require('path');
|
||||
var minimist = require('minimist');
|
||||
|
||||
var options = minimist(process.argv.slice(2), {
|
||||
string: ['dist'],
|
||||
boolean: ['headless'],
|
||||
default: {
|
||||
headless: implicitHeadless(),
|
||||
dist: 'dist'
|
||||
}
|
||||
});
|
||||
|
||||
function implicitHeadless() {
|
||||
return process.platform != 'win32' && process.platform != 'darwin' &&
|
||||
!process.env.DISPLAY;
|
||||
}
|
||||
|
||||
function startSession(session) {
|
||||
// an variant of https://git.io/vQ8o7
|
||||
chromedriver.start(['--url-base=wd/hub']);
|
||||
|
||||
var browser = webdriverio.remote({
|
||||
port: 9515, // TODO: autochoose choose unused port
|
||||
desiredCapabilities: {
|
||||
browserName: 'chrome',
|
||||
chromeOptions: options.headless ? {
|
||||
// see: https://goo.gl/ypWDst
|
||||
args: ['--headless', '--disable-gpu']
|
||||
} : {}
|
||||
}
|
||||
}).init().url('about:blank');
|
||||
|
||||
browser.on('error', (e) => console.error(e));
|
||||
|
||||
let br = session(browser, path.join(__dirname, '..')) || browser; // test dir
|
||||
br.end().then(() => chromedriver.stop());
|
||||
}
|
||||
|
||||
module.exports = startSession;
|
||||
111
static/js/ketcher2/test/utils/collections.js
Normal file
111
static/js/ketcher2/test/utils/collections.js
Normal file
@ -0,0 +1,111 @@
|
||||
/****************************************************************************
|
||||
* Copyright 2017 EPAM Systems
|
||||
*
|
||||
* Licensed 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.
|
||||
***************************************************************************/
|
||||
|
||||
/* eslint-env node */
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var minimist = require('minimist');
|
||||
|
||||
var options = minimist(process.argv.slice(2), {
|
||||
string: ['fixtures'],
|
||||
default: {
|
||||
fixtures: 'fixtures'
|
||||
}
|
||||
});
|
||||
|
||||
function collect(items, base) {
|
||||
var res = [];
|
||||
var structfiles = [];
|
||||
for (var fn of items) {
|
||||
var fpath = path.join(base || '', fn);
|
||||
if (fs.statSync(fpath).isDirectory())
|
||||
res = res.concat(collect(fs.readdirSync(fpath), fpath));
|
||||
else if (path.extname(fn) == '.sdf')
|
||||
res.push(sdfCollect(fpath));
|
||||
else if (!!base && ['.mol', '.rxn'].indexOf(path.extname(fn)) != -1)
|
||||
structfiles.push(fn);
|
||||
}
|
||||
if (structfiles.length > 0) {
|
||||
res.push({
|
||||
name: path.basename(base),
|
||||
path: base,
|
||||
type: 'folder',
|
||||
files: structfiles
|
||||
});
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function sdfCollect(fpath) {
|
||||
var data = fs.readFileSync(fpath, 'utf8');
|
||||
return {
|
||||
name: path.basename(fpath),
|
||||
path: fpath,
|
||||
type: 'sdf',
|
||||
count: data.split(/\$\$\$\$/).length
|
||||
};
|
||||
}
|
||||
|
||||
function* iterate(col) {
|
||||
if (col.type == 'folder') {
|
||||
for (var fn of col.files) {
|
||||
yield {
|
||||
name: fn,
|
||||
data: fs.readFileSync(path.join(col.path, fn), 'utf8')
|
||||
};
|
||||
}
|
||||
} else {
|
||||
var sdf = fs.readFileSync(col.path, 'utf8');
|
||||
var re = /^\$\$\$\$\n/gm;
|
||||
for (var m, i, num = 0; i = re.lastIndex, m = re.exec(sdf); num++) {
|
||||
yield {
|
||||
name: num,
|
||||
data: sdf.slice(i, m.index)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function range(n, start) {
|
||||
start = start || 0;
|
||||
return Array.apply(null, {
|
||||
length: n - start
|
||||
}).map((_, i) => i + start);
|
||||
}
|
||||
|
||||
function collection(collections, name) {
|
||||
var col = collections.find(c => c.name == name);
|
||||
return Object.assign(iterate(col), col.type == 'folder' ? {
|
||||
names: () => col.files,
|
||||
fixture: id => fs.readFileSync(path.join(col.path, id), 'utf8')
|
||||
} : {
|
||||
names: () => range(col.count - 1),
|
||||
fixture: id => {
|
||||
var data = fs.readFileSync(col.path, 'utf8');
|
||||
return data.split(/\$\$\$\$/m, id + 1)[id - 0].trim();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function (colPath) {
|
||||
if (!colPath) colPath = path.join('test/', options.fixtures);
|
||||
var cols = collect(Array.isArray(colPath) ? colPath : [colPath]);
|
||||
return Object.assign(collection.bind(null, cols), {
|
||||
names: () => cols.map(c => c.name)
|
||||
});
|
||||
};
|
||||
62
static/js/ketcher2/test/utils/generate-svg.js
Normal file
62
static/js/ketcher2/test/utils/generate-svg.js
Normal file
@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
* Copyright 2017 EPAM Systems
|
||||
*
|
||||
* Licensed 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.
|
||||
***************************************************************************/
|
||||
|
||||
/* eslint-env node */
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var ora = require('ora');
|
||||
var svgstore = require('svgstore');
|
||||
|
||||
var cols = require('./collections')();
|
||||
var browserSession = require('./browser-session');
|
||||
|
||||
browserSession((browser, testDir) => {
|
||||
browser = browser.url(`${testDir}/render/render-test.html`);
|
||||
|
||||
var sprites = svgstore({
|
||||
copyAttrs: ['width', 'height', 'preserveAspectRatio']
|
||||
});
|
||||
|
||||
for (var colname of cols.names()) {
|
||||
for (var name of cols(colname).names()) {
|
||||
let sampleName = `${colname}/${name}`;
|
||||
let structStr = cols(colname).fixture(name);
|
||||
|
||||
let opts = {
|
||||
sample: sampleName,
|
||||
width: 600,
|
||||
height: 400
|
||||
};
|
||||
let spinner = ora(sampleName);
|
||||
browser.then(() => spinner.start());
|
||||
browser = browser
|
||||
.execute(function (structStr, opts) {
|
||||
window.renderTest(structStr, opts);
|
||||
}, structStr, opts)
|
||||
.waitForExist('#canvas-ketcher')
|
||||
.getHTML('#canvas-ketcher', false).then(svg => {
|
||||
// console.info(sampleName, svg.replace(/.*(viewBox=".+?").*/, "$1"));
|
||||
sprites.add(sampleName, svg);
|
||||
spinner.succeed();
|
||||
});
|
||||
}
|
||||
}
|
||||
return browser.then(() => {
|
||||
// TODO should it be cmd arg?
|
||||
fs.writeFileSync('test/fixtures/fixtures.svg', sprites);
|
||||
});
|
||||
});
|
||||
34
static/js/ketcher2/test/utils/library.js
Normal file
34
static/js/ketcher2/test/utils/library.js
Normal file
@ -0,0 +1,34 @@
|
||||
/****************************************************************************
|
||||
* Copyright 2017 EPAM Systems
|
||||
*
|
||||
* Licensed 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.
|
||||
***************************************************************************/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const xpath = require('xpath');
|
||||
const DOMParser = require('xmldom').DOMParser;
|
||||
const XMLSerializer = require('xmldom').XMLSerializer;
|
||||
|
||||
let libStr = fs.readFileSync(path.join(__dirname, '../fixtures/fixtures.svg')).toString();
|
||||
let library = new DOMParser().parseFromString(libStr);
|
||||
|
||||
function libSymbol(sampleName) {
|
||||
let xsym = xpath.evaluate(`//*[@id='${sampleName}']`, library, // ids with '/' are absolutely valid, see https://epa.ms/SGNMm
|
||||
null, xpath.XPathResult.FIRST_ORDERED_NODE_TYPE, null);
|
||||
let symbol = xsym.singleNodeValue;
|
||||
return new XMLSerializer().serializeToString(symbol);
|
||||
}
|
||||
|
||||
module.exports = libSymbol;
|
||||
138
static/js/ketcher2/test/utils/molcompare.js
Normal file
138
static/js/ketcher2/test/utils/molcompare.js
Normal file
@ -0,0 +1,138 @@
|
||||
/****************************************************************************
|
||||
* Copyright 2017 EPAM Systems
|
||||
*
|
||||
* Licensed 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';
|
||||
|
||||
const defaultCmpOptions = {
|
||||
stripSpaces: false,
|
||||
skipCompare: [],
|
||||
eps: 0.00011
|
||||
};
|
||||
|
||||
const numberPattern = /-?\d+[\.,]?\d*/g;
|
||||
|
||||
function epsEqu(x, y, eps) {
|
||||
eps = eps || Number.EPSILON * Math.max(Math.abs(x), Math.abs(y));
|
||||
return Math.abs(x - y) <= eps;
|
||||
}
|
||||
|
||||
function arraysEquals(sArray, rArray, eqFunc) {
|
||||
return sArray === rArray ||
|
||||
(
|
||||
sArray.length === rArray.length &&
|
||||
sArray.every((elem, index) => eqFunc ? eqFunc(elem, rArray[index]) : elem === rArray[index])
|
||||
);
|
||||
}
|
||||
|
||||
function extractNumbers(source) {
|
||||
const matches = source.match(numberPattern);
|
||||
return {
|
||||
numbers: matches ? matches.map(parseFloat) : [],
|
||||
characters: source.replace(numberPattern, '').split(/\s+/)
|
||||
};
|
||||
}
|
||||
|
||||
function compareFile(source, dest, options) {
|
||||
const sourceStr = source.split(/\r?\n+/);
|
||||
const destStr = dest.split(/\r?\n+/);
|
||||
|
||||
for (var i = 0; i < sourceStr.length; i++) {
|
||||
if (options.stripSpaces) {
|
||||
sourceStr[i] = sourceStr[i].trim();
|
||||
destStr[i] = destStr[i].trim();
|
||||
}
|
||||
|
||||
const sDataSplitted = extractNumbers(sourceStr[i]);
|
||||
const rDataSplitted = extractNumbers(destStr[i]);
|
||||
|
||||
const numberEquals = arraysEquals(sDataSplitted.numbers, rDataSplitted.numbers, (x, y) => epsEqu(x, y, options.eps));
|
||||
const characterEquals = arraysEquals(sDataSplitted.characters, rDataSplitted.characters);
|
||||
|
||||
if (!numberEquals || !characterEquals)
|
||||
throw new Error(`\nsource: '${sourceStr[i]}'\ndest: '${destStr[i]}'`);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function compareRaw(source, dest, options) {
|
||||
const sDataMols = source.split('M END');
|
||||
const rDataMols = dest.split('M END');
|
||||
let newSdata, newRdata;
|
||||
|
||||
if (sDataMols.length !== rDataMols.length)
|
||||
throw new Error(`\nCount of content blocks are not equal: source = ${sDataMols.length}, dest = ${rDataMols.length}`);
|
||||
|
||||
options = Object.assign({}, defaultCmpOptions, options);
|
||||
|
||||
for (let i = 0; i < sDataMols.length - 1; i++) {
|
||||
const sV2000DataIndex = sDataMols[i].indexOf('V2000\n');
|
||||
const sV3000DataIndex = sDataMols[i].indexOf('V3000\n');
|
||||
|
||||
const rV2000DataIndex = rDataMols[i].indexOf('V2000\n');
|
||||
const rV3000DataIndex = rDataMols[i].indexOf('V3000\n');
|
||||
|
||||
newSdata = sDataMols[i].substring(6 + (sV3000DataIndex === -1 ? sV2000DataIndex : sV3000DataIndex));
|
||||
newRdata = rDataMols[i].substring(6 + (rV3000DataIndex === -1 ? rV2000DataIndex : rV3000DataIndex));
|
||||
|
||||
if (!compareFile(newSdata, newRdata, options))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function compareObjects(source, dest, options, parentKey) {
|
||||
if (typeof source !== typeof dest)
|
||||
throw new Error(`\ntypes not equal: type ${typeof source} of ${source} vs type ${typeof dest} of ${dest} in ${parentKey}`);
|
||||
|
||||
if (typeof source !== 'object')
|
||||
return source === dest;
|
||||
|
||||
return Object.keys(source)
|
||||
.filter(prop => !options.skipCompare.includes(prop))
|
||||
.every(key => {
|
||||
if (dest[key] === undefined)
|
||||
throw new Error(`\nDest object has no key ${key}`);
|
||||
|
||||
if (!compareObjects(source[key], dest[key], options, key))
|
||||
throw new Error(`\nsource: '${source[key]}'\ndest: '${dest[key]}' in ${key}`);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
function unicodeLiteral(str) {
|
||||
function fixedHex(number, length) {
|
||||
let str = number.toString(16).toUpperCase();
|
||||
while (str.length < length)
|
||||
str = "0" + str;
|
||||
return str;
|
||||
}
|
||||
let result = "";
|
||||
for (var i = 0; i < str.length; ++i) {
|
||||
if (str.charCodeAt(i) > 126 || str.charCodeAt(i) < 32)
|
||||
result += "\\u" + fixedHex(str.charCodeAt(i), 4);
|
||||
else
|
||||
result += str[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
raw: compareRaw,
|
||||
objects: compareObjects,
|
||||
unicodeLiteral: unicodeLiteral
|
||||
};
|
||||
Reference in New Issue
Block a user