new(basic.gblib): WEb Automation HOVER and LINK BY TEXT keywords.
This commit is contained in:
parent
ee5b9a7567
commit
f5826e1f0d
5 changed files with 127 additions and 42 deletions
1
gbot.sh
Executable file
1
gbot.sh
Executable file
|
@ -0,0 +1 @@
|
|||
node .
|
|
@ -86,7 +86,7 @@ export class DialogKeywords {
|
|||
hrOn: string;
|
||||
|
||||
step: GBDialogStep;
|
||||
|
||||
|
||||
public async getDeployer() {
|
||||
return this.min.deployService;
|
||||
}
|
||||
|
@ -124,8 +124,8 @@ export class DialogKeywords {
|
|||
*
|
||||
* @example x = GET PAGE
|
||||
*/
|
||||
public async getPage(step, url) {
|
||||
|
||||
public async getPage(step, url, username, password) {
|
||||
GBLog.info(`BASIC: Web Automation GET PAGE ${url}.`);
|
||||
if (!this.browser) {
|
||||
this.browser = await puppeteer.launch({
|
||||
args: [
|
||||
|
@ -138,8 +138,14 @@ export class DialogKeywords {
|
|||
ignoreHTTPSErrors: true,
|
||||
headless: false,
|
||||
});
|
||||
|
||||
// set the HTTP Basic Authentication credential
|
||||
|
||||
}
|
||||
const page = await this.browser.newPage();
|
||||
if (username || password) {
|
||||
await page.authenticate({ 'username': username, 'password': password });
|
||||
}
|
||||
await page.goto(url);
|
||||
return page;
|
||||
}
|
||||
|
@ -237,12 +243,24 @@ export class DialogKeywords {
|
|||
/**
|
||||
* Find element on page DOM.
|
||||
*
|
||||
* @example GET page, "elementName", "text"
|
||||
* @example GET page, "elementName"
|
||||
*/
|
||||
public async getBySelector(page, elementName) {
|
||||
GBLog.info(`BASIC: Web Automation GET element: ${elementName}.`);
|
||||
await page.waitForSelector(elementName)
|
||||
let element = await page.$(elementName);
|
||||
return element;
|
||||
let elements = await page.$$(elementName);
|
||||
if (elements && elements.length > 1) {
|
||||
return elements;
|
||||
}
|
||||
else {
|
||||
const el = elements[0];
|
||||
el['originalSelector'] = elementName;
|
||||
el['href'] = await page.evaluate(e => e.getAttribute('href'), el);
|
||||
el['value'] = await page.evaluate(e => e.getAttribute('value'), el);
|
||||
el['name'] = await page.evaluate(e => e.getAttribute('name'), el);
|
||||
el['class'] = await page.evaluate(e => e.getAttribute('class'), el);
|
||||
return el;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -251,31 +269,59 @@ export class DialogKeywords {
|
|||
* @example GET page, "frameSelector, "elementSelector"
|
||||
*/
|
||||
public async getByFrame(page, frame, selector) {
|
||||
GBLog.info(`BASIC: Web Automation GET element by frame: ${selector}.`);
|
||||
await page.waitForSelector(frame)
|
||||
let frameHandle = await page.$(frame);
|
||||
const f = await frameHandle.contentFrame();
|
||||
await f.waitForSelector(selector);
|
||||
const element = await f.$(selector);
|
||||
element['originalSelector'] = selector;
|
||||
element['href'] = await f.evaluate(e => e.getAttribute('href'), element);
|
||||
element['value'] = await f.evaluate(e => e.getAttribute('value'), element);
|
||||
element['name'] = await f.evaluate(e => e.getAttribute('name'), element);
|
||||
element['class'] = await f.evaluate(e => e.getAttribute('class'), element);
|
||||
element['frame'] = f;
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the today data filled in dd/mm/yyyy or mm/dd/yyyy.
|
||||
* Simulates a mouse hover an web page element.
|
||||
*/
|
||||
public async hover(step, page, idOrName) {
|
||||
GBLog.info(`BASIC: Web Automation HOVER element: ${idOrName}.`);
|
||||
await this.getBySelector(page, idOrName);
|
||||
await page.hover(idOrName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicks on an element in a web page.
|
||||
*
|
||||
* @example x = TODAY
|
||||
*/
|
||||
public async click(step, page, idOrName) {
|
||||
const e = await this.getBySelector(page, idOrName);
|
||||
|
||||
await Promise.all([
|
||||
page.waitForNavigation(),
|
||||
page.click(e.name)
|
||||
]);
|
||||
public async click(step, page, frameOrSelector, selector) {
|
||||
GBLog.info(`BASIC: Web Automation CLICK element: ${frameOrSelector}.`);
|
||||
if (selector) {
|
||||
await page.waitForSelector(frameOrSelector)
|
||||
let frameHandle = await page.$(frameOrSelector);
|
||||
const f = await frameHandle.contentFrame();
|
||||
await f.waitForSelector(selector);
|
||||
await f.click(selector);
|
||||
}
|
||||
else {
|
||||
await page.waitForSelector(frameOrSelector);
|
||||
await page.click(frameOrSelector);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async linkByText(step, page, text, index) {
|
||||
GBLog.info(`BASIC: Web Automation CLICK LINK TEXT: ${text} ${index}.`);
|
||||
if (!index) {
|
||||
index = 1
|
||||
}
|
||||
const els = await page.$x(`//a[contains(., '${text}')]`);
|
||||
await els[index - 1].click();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -285,6 +331,7 @@ export class DialogKeywords {
|
|||
* @example file = SCREENSHOT page
|
||||
*/
|
||||
public async screenshot(step, page, idOrName, localName) {
|
||||
GBLog.info(`BASIC: Web Automation SCREENSHOT ${idOrName}.`);
|
||||
const e = await this.getBySelector(page, idOrName);
|
||||
await e.screenshot({ path: localName });
|
||||
}
|
||||
|
@ -296,8 +343,9 @@ export class DialogKeywords {
|
|||
* @example TYPE page, "elementName", "text"
|
||||
*/
|
||||
public async type(step, page, idOrName, text) {
|
||||
GBLog.info(`BASIC: Web Automation TYPE on ${idOrName}: ${text}.`);
|
||||
const e = await this.getBySelector(page, idOrName);
|
||||
await e.type(text);
|
||||
await e.type(text, { delay: 200 });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -306,6 +354,7 @@ export class DialogKeywords {
|
|||
* @example x = TODAY
|
||||
*/
|
||||
public async getOCR(step, localFile) {
|
||||
GBLog.info(`BASIC: OCR processing on ${localFile}.`);
|
||||
const tesseract = require("node-tesseract-ocr")
|
||||
|
||||
const config = {
|
||||
|
@ -407,12 +456,11 @@ export class DialogKeywords {
|
|||
|
||||
}
|
||||
|
||||
public getCoded(value){
|
||||
public getCoded(value) {
|
||||
|
||||
// Checks if it is a GB FILE object.
|
||||
|
||||
if (value.data && value.filename)
|
||||
{
|
||||
if (value.data && value.filename) {
|
||||
value = value.data;
|
||||
}
|
||||
|
||||
|
@ -687,6 +735,21 @@ export class DialogKeywords {
|
|||
this.user = user;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines the maximum lines to scan in spreedsheets.
|
||||
*
|
||||
* @example SET MAX COLUMNS 5000
|
||||
*
|
||||
*/
|
||||
public async setMaxColumns(step, count) {
|
||||
const user = await this.min.userProfile.get(step.context, {});
|
||||
user.basicOptions.maxColumns = count;
|
||||
await this.min.userProfile.set(step.context, user);
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines the FIND behaviour to consider whole words while searching.
|
||||
*
|
||||
|
|
|
@ -324,41 +324,41 @@ export class GBVMService extends GBService {
|
|||
});
|
||||
|
||||
code = code.replace(/(\w+)\s*\=\s*get\s(.*)/gi, ($0, $1, $2, $3) => {
|
||||
|
||||
const count = ($2.match(/\,/g) || []).length;
|
||||
const values = $2.split(',');
|
||||
|
||||
// Handles GET page, "selector".
|
||||
const count = ($2.match(/\,/g) || []).length;
|
||||
const values = $2.split(',');
|
||||
|
||||
if (count == 1) {
|
||||
// Handles GET page, "selector".
|
||||
|
||||
return `${$1} = this.getByIDOrName(${values[0]}, ${values[1]} )`;
|
||||
}
|
||||
if (count == 1) {
|
||||
|
||||
// Handles GET page, "frameSelector", "selector"
|
||||
return `${$1} = this.getBySelector(${values[0]}, ${values[1]} )`;
|
||||
}
|
||||
|
||||
else if (count == 2) {
|
||||
// Handles GET page, "frameSelector", "selector"
|
||||
|
||||
return `${$1} = this.getByFrame(${values[0]}, ${values[1]}, ${values[2]} )`;
|
||||
}
|
||||
else if (count == 2) {
|
||||
|
||||
// Handles the GET http version.
|
||||
return `${$1} = this.getByFrame(${values[0]}, ${values[1]}, ${values[2]} )`;
|
||||
}
|
||||
|
||||
else {
|
||||
// Handles the GET http version.
|
||||
|
||||
else {
|
||||
|
||||
return `${$1} = sys().get (${$2}, headers)`;
|
||||
}
|
||||
|
||||
return `${$1} = sys().get (${$2}, headers)`;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
code = code.replace(/\= NEW OBJECT/gi, ($0, $1, $2, $3) => {
|
||||
return ` = {}`;
|
||||
});
|
||||
|
||||
|
||||
code = code.replace(/\= NEW ARRAY/gi, ($0, $1, $2, $3) => {
|
||||
return ` = []`;
|
||||
});
|
||||
|
||||
|
||||
|
||||
code = code.replace(/(go to)(\s)(.*)/gi, ($0, $1, $2, $3) => {
|
||||
return `gotoDialog(step, ${$3})\n`;
|
||||
|
@ -392,6 +392,10 @@ export class GBVMService extends GBService {
|
|||
return `setMaxLines (step, ${$3})\n`;
|
||||
});
|
||||
|
||||
code = code.replace(/(set max columns)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
|
||||
return `setMaxColumns (step, ${$3})\n`;
|
||||
});
|
||||
|
||||
code = code.replace(/(set translator)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
|
||||
return `setTranslatorOn (step, "${$3.toLowerCase()}")\n`;
|
||||
});
|
||||
|
@ -467,11 +471,19 @@ export class GBVMService extends GBService {
|
|||
code = code.replace(/(send mail)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
|
||||
return `sendEmail (${$3})\n`;
|
||||
});
|
||||
|
||||
|
||||
code = code.replace(/(send file to)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
|
||||
return `sendFileTo (step, ${$3})\n`;
|
||||
});
|
||||
|
||||
code = code.replace(/(hover)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
|
||||
return `hover (step, ${$3})\n`;
|
||||
});
|
||||
|
||||
code = code.replace(/(click link text)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
|
||||
return `linkByText (step, ${$3})\n`;
|
||||
});
|
||||
|
||||
code = code.replace(/(click)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
|
||||
return `click (step, ${$3})\n`;
|
||||
});
|
||||
|
@ -745,10 +757,16 @@ export class GBVMService extends GBService {
|
|||
code = code.replace(/("[^"]*"|'[^']*')|\bclick\b/gi, ($0, $1) => {
|
||||
return $1 === undefined ? 'this.click' : $1;
|
||||
});
|
||||
code = code.replace(/("[^"]*"|'[^']*')|\blinkByText\b/gi, ($0, $1) => {
|
||||
return $1 === undefined ? 'this.linkByText' : $1;
|
||||
});
|
||||
code = code.replace(/("[^"]*"|'[^']*')|\bhover\b/gi, ($0, $1) => {
|
||||
return $1 === undefined ? 'this.hover' : $1;
|
||||
});
|
||||
code = code.replace(/("[^"]*"|'[^']*')|\bsendEmail\b/gi, ($0, $1) => {
|
||||
return $1 === undefined ? 'this.sendEmail' : $1;
|
||||
});
|
||||
// await insertion.
|
||||
// await insertion.
|
||||
|
||||
code = code.replace(/this\./gm, 'await this.');
|
||||
code = code.replace(/\nfunction/i, 'async function');
|
||||
|
|
|
@ -422,7 +422,7 @@ export class SystemKeywords {
|
|||
*/
|
||||
public async wait(seconds: number) {
|
||||
// tslint:disable-next-line no-string-based-set-timeout
|
||||
GBLog.info(`BASIC: Talking to a specific user (TALK TO).`);
|
||||
GBLog.info(`BASIC: WAIT for ${seconds} second(s).`);
|
||||
const timeout = async (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
await timeout(seconds * 1000);
|
||||
}
|
||||
|
@ -575,15 +575,18 @@ export class SystemKeywords {
|
|||
}
|
||||
|
||||
let body = { values: [[]] };
|
||||
for (let index = 0; index < 128; index++) {
|
||||
|
||||
const address = `A2:${this.numberToLetters(args.length - 1)}2`;
|
||||
for (let index = 0; index < args.length; index++) {
|
||||
let value = args[index];
|
||||
if (value && this.isValidDate(value)) {
|
||||
value = `'${value}`;
|
||||
}
|
||||
body.values[0][index] = value;
|
||||
}
|
||||
|
||||
await client
|
||||
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A2:DX2')`)
|
||||
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${address}')`)
|
||||
.patch(body);
|
||||
}
|
||||
|
||||
|
|
|
@ -988,7 +988,7 @@ export class GBMinService {
|
|||
user.subjects = [];
|
||||
user.cb = undefined;
|
||||
user.welcomed = false;
|
||||
user.basicOptions = { maxLines: 100, translatorOn: true, wholeWord: true, theme: "white" };
|
||||
user.basicOptions = { maxLines: 100, translatorOn: true, wholeWord: true, theme: "white", maxColumns: 40 };
|
||||
|
||||
firstTime = true;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue