Skip to content

Commit

Permalink
Merge pull request #31 from softrams/new-implementation
Browse files Browse the repository at this point in the history
Browser config updates
  • Loading branch information
mkmurali authored Jul 28, 2023
2 parents d458e1d + 9c7dad8 commit bbe14ff
Show file tree
Hide file tree
Showing 8 changed files with 3,697 additions and 11,397 deletions.
28 changes: 23 additions & 5 deletions AvailableSteps.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@
## Web page steps

### Page navigation
- Goto `url`
- Goto `url` _or_ Open `url`
- Goto `url` in new tab _or_ Open `url` in new tab

### Switch to window tab
- Switch to `url` _or_ Switch to `url` window

### Close window tab
- Close window tab _or_ Close window

### Check for elements with specific text and other conditions
- Check `eleType` with text `text` and value `idx` matching `regex` to be `val`
Expand All @@ -23,6 +30,8 @@
- Check `eleType` with text `text` is disabled
- Check `eleType` with text `text` is enabled
- Check `eleType` with text `text` matches `regex`
- Verify `element` `elementText` `elementState` _or_ Verify `element` `elementText` is `elementState`
- Verify `element` text is `elementText`

### Proximity selector based steps
- Check `eleType` closer `proximity` text `text` does not exist
Expand All @@ -34,29 +43,38 @@
- Check text `text` exists

### Interact with form elements
- Clear `textbox`
- Clear `textbox` _or_ Clear `element` text box
- Click `eleType` closer `proximity` text `text`
- Click `eleType` with text `text`
- Click `text`
- Click `eleType` with text `text`, Click `element with text elementText`, Click on `element with text elementText` _or_ Click `element` for `elementText`
- Click `text` _or_ Click on `text`
- Click `text` in spec memory
- Click text `text` closer `proximity` text `proximityText`
- Double click `text`
- Focus text `text`
- Highlight text `text`
- Press `key`
- Scroll down `intValue`
- Select `value` from dropDown `dropDown`
- Scroll to `element`
- Select `value` from dropDown `dropDown` _or_ Select `value` from `element` dropdown
- Write `text` from property into `textbox`
- Write `text` from spec memory into `textbox`
- Write `text` into `textbox`
- Write `text` into `textbox` closer `proximity` text `proximityText`
- Write `text` into `textbox` no error
- Write `text` into dateField with text `textbox`
- Write `text` into textbox array `textArray` in data table
- Enter `value` to `element` text box _or_ Enter `value` to `element`
- Validate number of `typeRecords` records and pagination

### Store element text/value to the scenario state
- Save `element` as `elementTextKey` _or_ Save `element` text as `elementTextKey`

### Wait for something
- Wait `milliseconds` milliseconds
- or alternatively, Wait `milliseconds`ms
- Wait `seconds` seconds _or_ Wait for `seconds` seconds
- Wait for `text`

### Store page object element(s)
- On `pageName` page

58 changes: 58 additions & 0 deletions lib/_helpers.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const { faker } = require("@faker-js/faker");
const moment = require("moment");

exports.parseString = text => {
let result = text;
try {
Expand All @@ -13,3 +16,58 @@ exports.getScenarioData = key => {
exports.storeScenarioData = (key, value) => {
gauge.dataStore.scenarioStore.put(key, value);
};

exports.getValue = value => {
let numberOfIterations = 0;
let subValue = "";
while (value.includes("{") && value.includes("}") && numberOfIterations < value.length) {
numberOfIterations++;
subValue = value.substring(value.indexOf("{") + 1, value.indexOf("}"));
value = value.replace("{" + subValue + "}", getDynamicValue(subValue));
}
return String(getDynamicValue(value));
};

const getDynamicValue = value => {
return process.env[value] || gauge.dataStore.scenarioStore.get(value) || getDate(value) || getFakeData(value) || value;
};

const getDate = value => {
if (value.startsWith("date.")) {
const values = value.substring(value.indexOf(".") + 1).split(".");
let date = new Date();
if (values.length == 1) {
moment(date).format(values[0])
return moment(date).format(values[0]);
} else if (values.length == 2) {
date.setDate(date.getDate() + Number(values[0]));
return moment(date).format(values[1]);
}
}
return null;
};

/**
* API Reference => https://fakerjs.dev/api/
* Usage examples: phone.number, phone.number(+1 ###-###-####), person.firstName
* @param {*} value
* @returns
*/
const getFakeData = value => {
const values = value.split(".");
if (values.length <= 1) {
return value;
}
const value1 = values[0].trim();
let value2 = values[1].trim();
if (faker.hasOwnProperty(value1)) {
const args = value2.substring(value2.indexOf("(") + 1, value2.indexOf(")"));
value2 = value2.replace("(" + args + ")", "")

if (faker[value1].hasOwnProperty(value2)) {
return args ? faker[value1][value2](isNaN(args) ? args : Number(args)) : faker[value1][value2]();
}
console.log(value2 + " property undefined in " + value1);
}
return null;
};
24 changes: 20 additions & 4 deletions lib/_init.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,37 @@
"use strict";
const taiko = require("taiko");
const path = require("path");
const helpers = require("./_helpers");
const { waitFor } = require("taiko");

const headless = process.env.headless_chrome || 'true';
const browser_for_each_scenario = process.env.browser_for_each_scenario;
const open_browser_after_test = process.env.open_browser_after_test || "false";
const open_browser_after_test = process.env.open_browser_after_test;

// Support to run inside docker
const docker_env = process.env.DOCKER_RUNTIME || 'false';
const docker_args = ['--disable-gpu', '--disable-dev-shm-usage', '--disable-setuid-sandbox', '--no-first-run', '--no-sandbox', '--no-zygote'];

let addl_browser_args = process.env.browser_args ? process.env.browser_args.split(',') : [];
addl_browser_args = process.env.window_size ? addl_browser_args.concat(process.env.window_size) : addl_browser_args;

const browser_args = docker_env === 'true' ? docker_args.concat(addl_browser_args) : addl_browser_args;

beforeSuite(async () => {
if (!browser_for_each_scenario || browser_for_each_scenario === 'false') {
await taiko.openBrowser({ headless: headless === 'true', args: browser_args});
}
taiko.setConfig({
navigationTimeout: Number((process.env.navigation_timeout || taiko.getConfig("navigationTimeout"))),
retryInterval: Number((process.env.retry_interval || taiko.getConfig("retryInterval"))),
retryTimeout: Number((process.env.retry_timeout || taiko.getConfig("retryTimeout"))),
waitForEvents: (process.env.wait_for_events ? process.env.wait_for_events.split(",") : taiko.getConfig("waitForEvents")),
highlightOnAction: (Boolean(process.env.highlight_on_action) && process.env.highlight_on_action === "true")
});
});

beforeScenario(async () => {
beforeScenario(async context => {
helpers.storeScenarioData("scenario name", context.currentScenario.name);
if (browser_for_each_scenario === "true") {
await taiko.openBrowser({
headless: headless === 'true',
Expand All @@ -29,6 +41,10 @@ beforeScenario(async () => {
}
});

beforeStep(async context => {
helpers.storeScenarioData("step name", context.currentStep.step.actualStepText);
});

afterStep(async () => {
if (process.env.screenshot_on_everystep === "true") {
const currentURL = await taiko.currentURL();
Expand All @@ -41,13 +57,13 @@ afterStep(async () => {

afterScenario(async () => {
await gauge.screenshot();
if (browser_for_each_scenario === "true") {
if (browser_for_each_scenario === "true" && (!open_browser_after_test || open_browser_after_test === 'false')) {
await taiko.closeBrowser();
}
});

afterSuite(async () => {
if (!open_browser_after_test) {
if (browser_for_each_scenario === "false" && (!open_browser_after_test || open_browser_after_test === 'false')) {
await taiko.closeBrowser();
}
});
Expand Down
99 changes: 74 additions & 25 deletions lib/_pageElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
const { readFile } = require("fs/promises");
const fs = require('fs');
const _helpers = require("./_helpers");
const assert = require('assert').strict;

const helpers = [ "evaluate", "to", "into", "accept", "dismiss", "setConfig", "getConfig", "waitFor", "repl" ];
const selectors = [ "$", "image", "link", "listItem", "button", "fileField", "timeField", "textBox", "dropDown", "checkBox", "radioButton", "text", "tableCell", "color", "range" ];
Expand Down Expand Up @@ -48,41 +49,42 @@ const getHelper = async (taiko, element) => {
const getSelector = async (taiko, element) => {
const hasSelector = selectors.some(selector => element.startsWith(selector));
if (hasSelector) {
const helperValue = element.trim().substring(0, element.indexOf(" "));
const selectorValue = element.trim().substring(0, element.indexOf(" "));
const elementValue = element.trim().substring(element.indexOf(" ") + 1);
const proximitySelector = await getProximitySelectors(taiko, elementValue);

switch (helperValue) {
let proximitySelector = await getProximitySelectors(taiko, elementValue);
proximitySelector = _helpers.parseString(proximitySelector);

switch (selectorValue) {
case "$":
return taiko.$(proximitySelector);
return await taiko.$(proximitySelector);
case "image":
return taiko.image(proximitySelector);
return await taiko.image(proximitySelector);
case "link":
return taiko.link(proximitySelector);
return await taiko.link(proximitySelector);
case "listItem":
return taiko.listItem(proximitySelector);
return await taiko.listItem(proximitySelector);
case "button":
return taiko.button(proximitySelector);
return await taiko.button(proximitySelector);
case "fileField":
return taiko.fileField(proximitySelector);
return await taiko.fileField(proximitySelector);
case "timeField":
return taiko.timeField(proximitySelector);
return await taiko.timeField(proximitySelector);
case "textBox":
return taiko.textBox(proximitySelector);
return await taiko.textBox(proximitySelector);
case "dropDown":
return taiko.dropDown(proximitySelector);
return await taiko.dropDown(proximitySelector);
case "checkBox":
return taiko.checkBox(proximitySelector);
return await taiko.checkBox(proximitySelector);
case "radioButton":
return taiko.radioButton(proximitySelector);
return await taiko.radioButton(proximitySelector);
case "text":
return taiko.text(proximitySelector);
return await taiko.text(new RegExp(proximitySelector + ""));
case "tableCell":
return taiko.tableCell(proximitySelector);
return await taiko.tableCell(proximitySelector);
case "color":
return taiko.color(proximitySelector);
return await taiko.color(proximitySelector);
case "range":
return taiko.range(proximitySelector);
return await taiko.range(proximitySelector);
default:
break;
}
Expand Down Expand Up @@ -125,22 +127,20 @@ exports.getPageElement = async (taiko, element) => {
if (_element !== element) {
return _element;
}

let elementText;
if (element.includes("with text")) {
const elementParts = element.split("with text");
element = elementParts[0].trim();
elementText = elementParts[1].trim();
}

const currentPageName = _helpers.getScenarioData("currentPageName");
let fileText = await getFileContent("./tests/pages/" + currentPageName + ".json");
let fileObject;
let hasElement;
if (fileText == null) {
fileText = await getFileContent("./tests/pages/common.json");
fileObject = JSON.parse(fileText);
hasElement = fileObject.hasOwnProperty(element);
}

fileObject = JSON.parse(fileText);
Expand All @@ -149,11 +149,60 @@ exports.getPageElement = async (taiko, element) => {
fileText = await getFileContent("./tests/pages/common.json");
fileObject = JSON.parse(fileText);
hasElement = fileObject.hasOwnProperty(element);
} else {
let elementLocatorValue = fileObject[element]
}
if (hasElement) {
let elementLocatorValue = fileObject[element];
elementLocatorValue = elementText ?
elementLocatorValue.replace("{text}", elementText) : elementLocatorValue;
return await taiko.$(elementLocatorValue);
}

return element;
}

exports.checkElementState = async (taiko, element, elementState) => {
const pageElement = await this.getPageElement(taiko, element);
switch (elementState) {
case "exist":
case "exists":
await this.scrollToElementView(taiko, pageElement);
await taiko.waitFor(async () => (await pageElement.exists()));
break;
case "displayed":
case "visible":
await this.scrollToElementView(taiko, pageElement);
await taiko.waitFor(pageElement);
break;
case "enabled":
await this.scrollToElementView(taiko, pageElement);
await taiko.waitFor(async () => !(await pageElement.isDisabled()));
break;
case "not exists":
let waitSeconds = 0;
let isPageElementExists = await pageElement.exists(1000, 200);
while (isPageElementExists && waitSeconds < 5) {
await taiko.waitFor(1000);
waitSeconds++;
isPageElementExists = await pageElement.exists(1000, 200);
}
if (isPageElementExists) {
assert.fail("Element exists!");
}
break;
case "not displayed":
case "not visible":
await taiko.waitFor(async () => !(await pageElement.isVisible()));
break;
case "not enabled":
case "disabled":
await this.scrollToElementView(taiko, pageElement);
await taiko.waitFor(async () => (await pageElement.isDisabled()));
break;
default:
assert.fail("Element state \"" + elementState + "\" undefined");
}
}

exports.scrollToElementView = async (taiko, element) => {
await taiko.scrollTo(await element, { blockAlignment: 'center', inlineAlignment: 'center' });
}
Loading

0 comments on commit bbe14ff

Please sign in to comment.