diff --git a/gbot.sh b/gbot.sh new file mode 100755 index 00000000..4ea1fa63 --- /dev/null +++ b/gbot.sh @@ -0,0 +1 @@ +node . diff --git a/packages/basic.gblib/services/DialogKeywords.ts b/packages/basic.gblib/services/DialogKeywords.ts index ecf11e82..6f486acb 100644 --- a/packages/basic.gblib/services/DialogKeywords.ts +++ b/packages/basic.gblib/services/DialogKeywords.ts @@ -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. * diff --git a/packages/basic.gblib/services/GBVMService.ts b/packages/basic.gblib/services/GBVMService.ts index afd2460f..9dfb91f1 100644 --- a/packages/basic.gblib/services/GBVMService.ts +++ b/packages/basic.gblib/services/GBVMService.ts @@ -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'); diff --git a/packages/basic.gblib/services/SystemKeywords.ts b/packages/basic.gblib/services/SystemKeywords.ts index d836326d..992ce55b 100644 --- a/packages/basic.gblib/services/SystemKeywords.ts +++ b/packages/basic.gblib/services/SystemKeywords.ts @@ -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); } diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index f4307a6d..df564d46 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -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;