Skip to content

Instantly share code, notes, and snippets.

@Yuyz0112
Created June 26, 2018 05:49
Show Gist options
  • Save Yuyz0112/a8ad3713171bb3ed8984c1104c747f10 to your computer and use it in GitHub Desktop.
Save Yuyz0112/a8ad3713171bb3ed8984c1104c747f10 to your computer and use it in GitHub Desktop.
const lodash = require('lodash');
const toArray = require('../utils/toArray');
const { CONSTANTS: C } = require('../globals');
const NAME_ALIAS = '名称';
function hint(options) {
const rules = ['Check your selector value.'];
if (!options.debug) {
rules.push('Add { debug: true } to your options to get more info.');
}
if (options.html) {
rules.push(
'MAKE SURE your selector values are Regexp because we are comparing it with innerHTML.'
);
}
const message = `
There is no index got in this command.
If this was not expected, you can:
${rules.map((rule, index) => `${index + 1}. ${rule}`).join('\r\n')}
`;
console.log(message);
}
function check(record, selector) {
let passed = true;
for (let col in selector) {
if (!selector[col]) {
return;
}
let matched = false;
const matchers = toArray(selector[col]);
for (let matcher of matchers) {
const isString = lodash.isString(matcher);
const isRegExp = lodash.isRegExp(matcher);
if (!isString && !isRegExp) {
throw new Error(`Invalid matcher ${matcher}.`);
}
if (isString && matcher === record[col]) {
matched = true;
}
if (isRegExp && matcher.test(record[col])) {
matched = true;
}
}
if (!matched) {
passed = false;
}
}
return passed;
}
exports.command = function(selector, options = {}) {
// unify options
if (lodash.isFunction(options)) {
options = {
cb: options,
};
}
const {
cb, // customize call back function
cssPrefix = '', // css prefix of the table
picker = 'first', // picker behavior
html, // collect innerHTML or innerText
keepSelector = false, // keep all selector in mock
debug, // log debug info
} = options;
// a wrapper of custom cb;
const _cb = function(error, indexes) {
if (debug) {
console.log('[debug]all indexes:', indexes);
console.log('[debug]picker:', picker);
}
switch (true) {
case !cb:
break;
case !!error:
cb(error);
break;
case indexes.length === 0:
case picker === 'all':
cb(null, indexes);
break;
case picker === 'first':
cb(null, [indexes[0]]);
break;
case picker === 'random':
cb(null, [indexes[lodash.random(indexes.length - 1)]]);
break;
case lodash.isFunction(picker):
cb(null, picker(indexes));
break;
default:
cb(new Error(`Invalid picker ${picker}.`));
}
// return a chainable client
return this.perform(() => {});
}.bind(this);
// if selector is a number, just return it as the index;
if (lodash.isNumber(selector)) {
return _cb(null, [selector]);
}
// unify selector
switch (true) {
case lodash.isString(selector):
case lodash.isRegExp(selector):
selector = { [NAME_ALIAS]: selector };
break;
case lodash.isArray(selector):
if (selector.every(lodash.isNumber)) {
return _cb(null, selector);
}
selector = { [NAME_ALIAS]: selector };
break;
default:
}
if (!lodash.isPlainObject(selector)) {
return _cb(new Error('Failed to unify the selector.'));
}
// mock env will ignore name selector
if (C.IS_MOCK && selector[NAME_ALIAS] && !keepSelector) {
selector[NAME_ALIAS] = /.*/;
}
// use cssPrefix to determine which selectable table need to be used.
const headerCol = `${cssPrefix} .wizard-table-thead th`;
const row = `${cssPrefix} .wizard-table-row`;
if (debug) {
console.log('[debug]selector:', selector);
console.log('[debug]row:', row);
}
this.waitForElementVisible(row).execute(
function(headerCol, row, html) {
const cols = document.querySelectorAll(headerCol);
const colMap = {};
for (let i = 0; i < cols.length; i++) {
colMap[i] = cols[i].innerText.trim();
}
const rows = document.querySelectorAll(row);
const records = [];
// parse row dom to standard record
for (let i = 0; i < rows.length; i++) {
const tr = {};
const tds = rows[i].querySelectorAll('td');
for (let index = 0; index < tds.length; index++) {
tr[colMap[index]] = html ? tds[index].innerHTML.trim() : tds[index].innerText.trim();
}
records.push(tr);
}
return records;
},
[headerCol, row, html],
function(result) {
if (!result.value || result.value.length === 0) {
return _cb(new Error('No rows found.'));
}
if (debug) {
console.log('[debug]:table records:\r\n', result.value);
}
const indexes = [];
try {
for (let index = 0; index < result.value.length; index++) {
if (check(result.value[index], selector)) {
indexes.push(index);
}
}
} catch (error) {
return _cb(error);
}
if (!indexes.length) {
hint(options);
}
return _cb(null, indexes);
}
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment