I want to write a script for testing dropdown inside the webpage. But, I was unable to do so in selenium using Nodejs. Is there any method to test dropdown in selenium(NodeJs).
Thanks in advance
You can create a select class like this and then use method based on your selection.
var SelectWrapper = function(selector) {
this.webElement = element(selector);
};
SelectWrapper.prototype.getOptions = function() {
return this.webElement.all(by.tagName('option'));
};
SelectWrapper.prototype.getSelectedOptions = function() {
return this.webElement.all(by.css('option[selected="selected"]'));
};
SelectWrapper.prototype.selectByValue = function(value) {
return this.webElement.all(by.css('option[value="' + value + '"]')).click();
};
SelectWrapper.prototype.selectByPartialText = function(text) {
return this.webElement.all(by.cssContainingText('option', text)).click();
};
SelectWrapper.prototype.selectByText = function(text) {
return this.webElement.all(by.xpath('option[.="' + text + '"]')).click();
};
module.exports = SelectWrapper;
Usage in test class
var SelectWrapper = require('./select-wrapper.js');
var mySelect = new SelectWrapper(by.id("validSelectTagID"));
describe("Select Wrapper",function(){
it("Handling the dropdown list",function(){
browser.get("http://validURL");
mySelect.selectByText("TextinDrop");
mySelect.selectByValue("ValueInDrop");
}) ;
Related
I'm trying to return the words in a text selection as a string in google docs. I can't figure out how to return anything other than the entire body of text in an element, and it seems like the smallest element is a paragraph. I ned smaller.
Attempt 1:
function printSelection1 () {
var string = DocumentApp.getActiveDocument().getText();
Logger.log(string);
}
This returns the entire body of the document, rather than the selection, as a string.
Attempt 2:
function printSelection2 () {
var selection = DocumentApp.getActiveDocument().getSelection();
var string =selection.asString();
Logger.log(string);
}
Error message: "TypeError: selection.asString is not a function."
Attempt 3:
function printSelection4 () {
var selection = DocumentApp.getActiveDocument().getSelection();
var getelements =selection.getSelectedElements();
var string = getelements.toString();
Logger.log(string);
}
This returns the string "RangeElement," rather than the string of the selection itself.
I feel like I'm close. Or maybe I'm not?
Use Document.getSelection() to get the selected Range and Range.getRangeElements() to get the elements in the Range, including any Text elements therein.
You are saying that you want to get "only the individual words that are selected." To get text that spans just a portion of an element, such as in the start and end of the selection, use RangeElement.isPartial() together with RangeElement.getStartOffset() and RangeElement.getEndOffsetInclusive(). When isPartial() returns false, you can use RangeElement.getElement().asText().getText() to get all the text in the element.
Here's an example of how to do this:
function printSelection() {
const selectedText = getSelectedText();
console.log(selectedText ? `The selected text is "${selectedText}".` : `No text is selected.`);
}
/**
* Gets the currently selected text in a document.
*
* #param {DocumentApp.Range} range Optional. The document range where to get text. Defaults to currently selected text.
* #return {String} The text in range joined with newlines, or an empty string when the range does not contain text.
*/
function getSelectedText(range = DocumentApp.getActiveDocument().getSelection()) {
const result = [];
if (range) {
range.getRangeElements().forEach(rangeElement => {
if (rangeElement.isPartial()) {
const startIndex = rangeElement.getStartOffset();
const endIndex = rangeElement.getEndOffsetInclusive();
result.push(rangeElement.getElement().asText().getText().substring(startIndex, endIndex + 1));
} else {
const element = rangeElement.getElement();
if (element.editAsText) {
const elementText = element.asText().getText();
if (elementText) {
result.push(elementText);
}
}
}
});
}
return result.length ? result.join('\n') : '';
}
This example is based on the partially outdated Docs quickstart.
This should help.
function getSelectedText() {
var text = DocumentApp.getActiveDocument()
.getSelection()
.getRangeElements()
.map((element) => element.getElement().asText().getText())
.join(" ");
Logger.log(text);
}
Would something like this suffice:
function printSelection() {
var selection = DocumentApp.getActiveDocument().getSelection();
if (selection) {
var range = selection.getRange();
var string = range.getText();
Logger.log(string);
} else {
Logger.log("No text is selected.");
}
}
EDIT: Judging by the error, it seems that getRange() is not available for the seleciton object...
You can try to use the getStartOffset() and getEndOffset():
function printSelection() {
var selection = DocumentApp.getActiveDocument().getSelection();
if (selection) {
var startIndex = selection.getStartOffset();
var endIndex = selection.getEndOffset();
var document = DocumentApp.getActiveDocument();
var string = document.getText().substring(startIndex, endIndex);
Logger.log(string);
} else {
Logger.log("No text is selected.");
}
}
Based on previous answers, improved for multi paragraph selection :
function printSelect() {
const r = DocumentApp.getActiveDocument().getSelection();
if (!r) {
return;
}
const tab = r.getRangeElements();
var output = "";
for (let x = 0; x < tab.length; x++) {
let start = tab[x].getStartOffset();
let end = tab[x].getEndOffsetInclusive();
let selection = tab[x].getElement().getText().substring(start, end);
output += selection || "\n\n"; //if selection is null == paragraph, so add double \n
}
Logger.log(output);
}
Suppose I have a test case like -
Scenario: Scenario to verify Title Matched
When Navigate to the App "Facebook"
Then verify the "TitleName" Field
How could I get the scenario name from the step definition methods corresponding to " When Navigate to the App Facebook" and "Then verify the "TitleName" Field"
Step definitions methods are -
When('Navigate to the App {string} for demo',(AppURL:string)=>{
if(AppURL=="FaceBook"){
}
});
Then('verify the Title of the page for demo',()=>
{
SampleAPPUI.verfiyTitledemo('');
});
Note: I am using cypres-cucumber with typescript
I'm doing this in a Java-Selenium-Gherkin test suite. It may not be the solution you need, but it will give you some direction about how to get the values:
#BeforeStep
public void doSomethingBeforeStep(Scenario scenario) throws Exception {
testScenario = scenario.getName().toString();
scenarioObj = scenario;
Field f = scenario.getClass().getDeclaredField("testCase");
f.setAccessible(true);
TestCase r = (TestCase) f.get(scenario);
List<PickleStepTestStep> stepDefs = r.getTestSteps()
.stream()
.filter(x -> x instanceof PickleStepTestStep)
.map(x -> (PickleStepTestStep) x)
.collect(Collectors.toList());
PickleStepTestStep currentStepDef = stepDefs.get(currentStepIndex);
testCase = currentStepDef.getStepText();
}
Also, see here and here
This works perfectly for me, though I'm not using TS, the logic behind it should give you a good starting point:
function getScenarioName(){
const _onRunnableRun = Cypress.runner.onRunnableRun
Cypress.runner.onRunnableRun = function (runnableRun, runnable, args) {
const r = runnable
const isHook = r.type === 'hook'
const isAfterAllHook = isHook && r.hookName.match(/after all/)
const isBeforeHook = isHook && r.hookName.match(/before each/)
const test = r.ctx.currentTest || r
var testTitle = test.title //this is the test title
const next = args[0]
if (
isHook &&
r.ctx.currentTest &&
r.ctx.currentTest.trueFn &&
!isAfterAllHook
) {
return next.call(this)
}
const onNext = function (err) {
const fail = function () {
return next.call(this, err)
}
const noFail = function () {
test.err = null
return next.call(this)
}
if (err) {
if (test._retries === -1) {
test._retries = getDefaultRetries()
}
if (isBeforeHook && test._currentRetry < test._retries) {
test.trueFn = test.fn
test.fn = function () {
throw err
}
return noFail()
}
}
return fail()
}
args[0] = onNext
return _onRunnableRun.apply(this, [runnableRun, runnable, args])
}
}
Is there a way to disable the line item field Amount?
Currently the Amount field is visible, and users can basically edit the Amount if they wish. The finance requested that the Fiedl Amount on the Quotation Form (“Estimate”) should be disable to prevent Sales Rep from change the Amount.
If click the Customize form and view the Sublist Field Amount, there is NO Option to disable the field.
You'll need to either just not show it on the form, in the columns (not a secure way of avoiding the issue). Or, you can script the field to be disabled when it it loaded on the form.
You should create a client script :
/**
* #NApiVersion 2.x
* #NScriptType ClientScript
*/
define(['N/record'],
function (record) {
function lineInit(context) {
try {
/** this will disable the amount for existing line */
var rec = context.currentRecord;
var itemCount = rec.getLineCount('item');
var sublistName = context.sublistId;
var line = rec.getCurrentSublistIndex({ sublistId: sublistName });
if (itemCount > line) {
var theField = rec.getSublistField({
sublistId: sublistName,
fieldId: 'amount',
line: line
});
theField.isDisabled = true;
}
/** this will hide the amount label for the new line : inspect the tag ID input#amount_formattedValue*/
if (!document.getElementById('hidden-amount-style')) {
var css = 'input#amount_formattedValue { display: none; }',
head = document.getElementsByTagName('head')[0],
style = document.createElement('style');
head.appendChild(style);
style.type = 'text/css';
style.id = 'hidden-amount-style';
style.appendChild(document.createTextNode(css));
}
} catch (e) {
console.error('🛑 lineInit', JSON.stringify(e, null, 4));
}
}
function pageInit(context) { }
function validateField(context) { return true; }
function fieldChanged(context) { }
function postSourcing(context) { }
function lineInit(context) { }
function validateDelete(context) { return true; }
function validateInsert(context) { return true; }
function validateLine(context) { return true; }
function sublistChanged(context) { }
function saveRecord(context) { return true }
return {
pageInit: pageInit,
fieldChanged: fieldChanged,
postSourcing: postSourcing,
sublistChanged: sublistChanged,
lineInit: lineInit,
validateField: validateField,
validateLine: validateLine,
validateInsert: validateInsert,
validateDelete: validateDelete,
saveRecord: saveRecord,
};
});
In Add Link page, is it possible to change the default values like title, address, show these links to, by using URL parameters?
According to this, it seems possible in sharepoint2010. Does anyone know whether it works in 2013??
If not, is it possible to add a link by post REST API??
This problem can be solved by the steps below.
Add a custom action. Just follow the steps here.
In my case code is as below
SP.SOD.executeFunc("callout.js", "Callout", function() {
var itemCtx = {};
itemCtx.Templates = {};
itemCtx.BaseViewID = 'Callout';
// Define the list template type
itemCtx.ListTemplateType = 101;
itemCtx.Templates.Footer = function(itemCtx) {
// context, custom action function, show the ECB menu (boolean)
return CalloutRenderFooterTemplate(itemCtx, AddCustomAction, true);
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(itemCtx);
});
function AddCustomAction(renderCtx, calloutActionMenu) {
// Add your custom action
calloutActionMenu.addAction(new CalloutAction({
text: "FAVORITE",
// tooltip: 'This is your custom action',
onClickCallback: function() {
CreateCustomNewQuickLink(renderCtx.CurrentItem.FileLeafRef, renderCtx.CurrentItem.FileRef);
}
}));
// Show the default document library actions
CalloutOnPostRenderTemplate(renderCtx, calloutActionMenu);
}
function CreateCustomNewQuickLink(title, url) {
var urlAddress = $(location).attr('protocol') + "//" + $(location).attr('host') + '/_Layouts/quicklinksdialogformTEST.aspx?Mode=Link' +
'&title=' + encodeURIComponent(title) +
'&url=' + encodeURIComponent(url);
ShowNewQuicklinkPopup(urlAddress, PageRefreshOnDialogClose);
}
Create a new add link page which is copied from "quicklinksdialogform.aspx". I add some javascript as below.
$(init)
function init() {
var args = new Object();
args = GetUrlParms();
if (args["title"] != undefined) {
$(".ms-long")[0].value = decodeURIComponent(args["title"]);
}
if (args["url"] != undefined) {
$(".ms-long")[1].value = decodeURIComponent(args["url"]);
}
}
function GetUrlParms() {
var args = new Object();
var query = location.search.substring(1);
var pairs = query.split("&");
for (var i = 0; i < pairs.length; i++) {
var pos = pairs[i].indexOf('=');
if (pos == -1) continue;
var argname = pairs[i].substring(0, pos);
var value = pairs[i].substring(pos + 1);
args[argname] = unescape(value);
}
return args;
}
It works like below
I use this function to watch an array of objects for changes:
$scope.$watch('Data', function (newVal) { /*...*/ }, true);
How can I get an object in which property has been changed so that I can push it in an array?
For example:
var myApp = angular.module("myApp", []);
myApp.factory("Data", function(){
var Data = [{id:1, property: "Random"}, {id:2, property: "Random again"}];
return Data;
});
var myBigArray = [];
function tableCtrl($scope, Data){
$scope.TheData = Data;
$scope.$watch("TheData", function() {
//Here an object should be pushed
myBigArray.push(">>Object in which property has been changed <<<");
}, true);
}
I don't see a way currently in Angular to get the changed object... I suspect you might need to traverse the new array and try to find the differences with the old array...
Edit: Note that this solution turns out to be a bad practice as it is adding a lot of watchers, which is something you do not want because it has a performance penalty.
=======
I eventually came up with this solution:
items.query(function (result) {
_(result).each(function (item, i) {
$scope.items.push(item);
$scope.$watch('items[' + i + ']' , function(){
console.log(item); // This is the item that changed.
}, true);
});
});
There is still no option like this for $watch, but you can use jQuery plugin for that, http://archive.plugins.jquery.com/project/jquery-diff
I implemented undo/redo with AngularJS using $watch, mb this can help
//History Manager Factory
.factory('HistoryManager', function () {
return function(scope) {
this.container = Array();
this.index = -1;
this.lock = false;
//Insert new step into array of steps
this.pushDo = function() {
//we make sure that we have real changes by converting to json,
//and getting rid of all hash changes
if(this.container.length == 0 || (angular.toJson(scope.widgetSlider) != angular.toJson(this.container[this.index][0]))) {
//check if current change didn't came from "undo" change'
if(this.lock) {
return;
}
//Cutting array, from current index, because of new change added
if(this.index < this.container.length-1) {
this.container = this.container.slice(0, this.index+1);
}
var currentStepSlider = angular.copy(scope.widgetSlider);
var selectedWidgetIndex = scope.widgetSlider.widgets.indexOf(scope.widgetCurrent);
//Initialising index, because of new "Do" added
this.index = this.container.length;
this.container.push([currentStepSlider, selectedWidgetIndex]);
if (this.onDo) {
this.onDo();
}
}
}
//Upon undo returns previous do
this.undo = function() {
this.lock = true;
if(this.index>0){
this.index--;
scope.widgetSlider = angular.copy(this.container[this.index][0]);
var selectedWidgetIndex = this.container[this.index][1];
scope.widgetCurrent = scope.widgetSlider.widgets[selectedWidgetIndex];
}
this.lock = false;
}
//Upon redo returns next do
this.redo = function() {
if(this.index < this.container.length-1) {
this.index++;
scope.widgetSlider = angular.copy(this.container[this.index][0]);
var selectedWidgetIndex = this.container[this.index][1];
scope.widgetCurrent = scope.widgetSlider.widgets[selectedWidgetIndex];
}
}
}
})
;