How to check if a web element is displayed without crashing when trying to look for non-existing element? - scala

I want to check id certain element is displayed with selenium, buy when you try to locate certain element like:
val editInvoiceString = driver.findElement(By.xpath( """//*[#id="edit_invoice"]/div[2]/div/div[10]/div[5]/div[1]"""))
editInvoiceString
if (editInvoiceString.isDisplayed)
do something
if the element is not on page the program will be crashed.
its crashing already in the assignment, cause there is a findElement there and its not finding the element
How can I check if it is displayed without crash it?

Just handle the NoSuchElementException:
try {
val editInvoiceString = driver.findElement(By.xpath( """//*[#id="edit_invoice"]/div[2]/div/div[10]/div[5]/div[1]"""));
println("element found");
// check the displayedness
}
catch {
case e: NoSuchElementException => println("no such element");
}

If you use driver.find instead of driver.findElement, it will return an Option, on which you can then call isDefined to verify that the element is found.
Are you using WebBrowser?

you can achieve it by:
public bool IsElementPresent(By by, IWebDriver driver)
{
try
{
driver.FindElement(by);
return true;
}
catch (NoSuchElementException)
{
return false;
}
}
public bool IsElementPresent(By by, IWebDriver driver, int sec)
{
bool itemExist = false;
itemExist = IsElementPresent(by, driver);
while (!itemExist && sec >= 0)
{
thread.Sleep(1);
itemExist = IsElementPresent(by, driver);
sec--;
}
if (sec == -1)
return false;
else
return true;
}
Call:
if(IsElementPresent(By.xpath("""//*[#id="edit_invoice"]/div[2]/div/div[10]/div[5]/div[1]"""),driver,5))
{
//case exist
}
else
{
// case not exist
}

You don't need to use a try-catch clause if you ignore the exception using the Wait class (which extends FluentWait):
Wait wait = new FluentWait(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(ExpectedConditions.presenceOfElementLocated(
By.xpath(".//*[#id="edit_invoice"]/div[2]/div/div[10]/div[5]/div[1]"))
);

Use findElements instead of FindElement.
This will return a list of WebElements found. If no elements are found the list will be empty. It would look something like this (Note I'm not a Scala person so the syntax below may be slightly incorrect).
val editInvoiceString = driver.findElements(By.xpath( """//*[#id="edit_invoice"]/div[2]/div/div[10]/div[5]/div[1]"""))
if (editInvoiceString size > 0)
do something

Related

check if clone is equal to original thing Unity

I'm working on a inventory system and i had working Crafting system, now i wanted to create RPG like crafting queue where you can click like 3 times on a item and it wil lcraft for you 3 time if you have enough resources, and i started working on it but for some reason, the original crafting system broke, here is what happens when you want to craft something
When you click on Crafting Recipe:
//override Use Function
public override void Use() {
//call AddCraftingItem from Inventory
Inventory.instance.AddCraftingItem(this);
}
AddCraftingItem:
public void AddCraftingItem(CraftinRecipe newCraftingRecipe) {
CraftingQueue.Enqueue(newCraftingRecipe);
if(!isCrafting) {
isCrafting = true;
//start crafting
StartCoroutine(CraftItem());
}
}
CraftItem:
private IEnumerator CraftItem() {
//check if queue is empty
if(CraftingQueue.Count == 0) {
Debug.Log("Queue is empty");
isCrafting = false;
yield break;
}
CraftinRecipe currentRecipe = CraftingQueue.Dequeue();
//check if we have enough resources
//this is where things broke
//CraftItem return false
if(!currentRecipe.CraftItem()) {
//Debug.Log("You don't have enough Resources");
CraftingQueue.Clear();
isCrafting = false;
yield break;
}
Debug.Log("TEST");
yield return new WaitForSeconds(currentRecipe.craftTime * 1.1f);
//add item to inventory
AddItem(currentRecipe.result);
Debug.Log("Added " + currentRecipe.result + " to inventory");
//check if continue crafting
if(CraftingQueue.Count > 0) {
yield return StartCoroutine(CraftItem());
} else {
isCrafting = false;
}
}
CraftItem:
public bool CraftItem() {
if(!CanCraft()) {
//Debug.Log("CanCraft returned false");
return false;
} else {
Debug.Log("CanCraft returned true");
}
RemoveIngredientsFromInventory();
//start crafting
ParentCraftingSlot.StartCrafting();
return true;
}
CanCraft function:
//function that return bool if we can craft the Item
public bool CanCraft() {
//loop trough each ingredient type of ingredient in ingredient
//(don't worry bro i don't understand what i just said too)
foreach(Ingredient ingredient in ingredients) {
//bool if we Contains current Ingredients
//here this function return false
bool ContainsCurrentIngredient = Inventory.instance.ContainsItem(ingredient.item,
ingredient.amount);
//if ContainsCurrentIngredient is false
if(!ContainsCurrentIngredient) {
//we return false
return false;
}
}
//return true
return true;
}
ContainItems (this is where things are broken):
//function that return true or false
//if we have enough Item to craft something
public bool ContainsItem(Item item, int amount) {
//make some variables objects etc
int ItemCounter = 0;
//loop through InventoryItemList with variable i type of Item
//(don't worry i don't know what i just said too #6)
foreach(Item i in InventoryItemList) {
//if i is equal to item
//this is the broken part
if(i == item) {
Debug.Log(i);
Debug.Log(item);
//we add 1 to Item Counter
ItemCounter++;
} else {
Debug.Log("i is not equal to item");
}
}
//if ItemCounter is bigger then or equal to amount
if(ItemCounter >= amount) {
/*Debug.Log("ContainsItem returned true");
Debug.Log(ItemCounter);*/
//we return true
//that means we have enough items to craft something
return true;
} else /*else*/ {
/*Debug.Log("ContainsItem returned false");
Debug.Log(ItemCounter);*/
//we return false
//that means we don't have enough item to craft something
return false;
}
}
so the problem is, in the InventoryItemList there are clones of one item, lets just say i have 2 irons and i need 1 iron to craft something, and my guess is that the problem is that i is clone so its not equal to the item and thats why it doesn't add 1 to itemCounter and then the script thinks we don't have enough resources to craft something, i tried to search and ask some of my friends how to check if that clone is equal to the item and i'm trying to fix this thing for like 2 days, i would love to hear any answers how to fix it or how to make my code more optimal, thanks for reading
Instead of directly checking i == item have some property in Item class which contains information of item type something like following
public class item
{
public enum Type
{
IronBar, GoldBar //etc
}
public Type itemType;
}
Then in your ContainItems() you could use something like
public bool ContainsItem(Item.Type itemType, int amount){
// other code
foreach(Item i in InventoryItemList) {
if(i.itemType == itemType) {
ItemCounter++;
}
// other code
}

Salesforce APEX Test Class for Simple Trigger

I've been going nuts over this. Nothing in my IF loop is firing through my test class and I cannot figure out why. I have done a lot of reading online and it appears that I am doing things correctly but it still hasn't solved my code coverage. This is the last line that runs:
If (isWithin == True){
after that I can't get anything to run within that IF loop, I have reversed the logic and it still doesn't run. I feel like I will kick myself when someone points it out but here is my code:
trigger caseCreatedDurringBusinessHours on Case (after insert) {
//Create list and map for cases
List<case> casesToUpdate = new List<case>();
Map<Id, case> caseMap = new Map<Id, case>();
// Get the default business hours
BusinessHours bh = [SELECT Id FROM BusinessHours WHERE IsDefault=true];
// Create Datetime on for now in the local timezone.
Datetime targetTime =System.now();
// Find whether the time now is within the default business hours
Boolean isWithin;
if ( Test.isRunningTest() ){
Boolean isWithin = True;
}
else{
Boolean isWithin = BusinessHours.isWithin(bh.id, targetTime);
}
// Update cases being inserted if during business hours
If (isWithin == True){
// Add cases to map if not null
For(case newcase : trigger.new) {
if(newcase.id != null){
caseMap.put(newcase.Id, newcase);
}
}
// Check that cases are in the map before SOQL query and update
If(caseMap.size() > 0){
// Query cases
casesToUpdate = [SELECT Id, Created_During_Business_Hours__c FROM case WHERE Id IN: caseMap.keySet()];
// Assign new value for checkbox field
for (case c: casesToUpdate){
c.Created_During_Business_Hours__c = TRUE;
}
// if the list of cases isnt empty, update them
if (casesToUpdate.size() > 0)
{
update casesToUpdate;
}
}
}
}
and here is my test class:
#isTest
private class BusinessHoursTest {
#isTest static void createCaseNotInBusinessHours() {
case c = new case();
c.subject = 'Test Subject';
insert c;
}
}
I think you can just copy the main logic to the apex class and just call the method of apex class from the apex trigger.
So it will make it more easy to write the test class.
Let me know if you need more help in this.
I'm sure you've figured this out by now but this block of code is re-defining the isWithin variable inside of the if/else blocks:
Boolean isWithin;
if (Test.isRunningTest()) {
Boolean isWithin = True;
} else {
Boolean isWithin = BusinessHours.isWithin(bh.id, targetTime);
}
That needs to be:
Boolean isWithin;
if (Test.isRunningTest()) {
isWithin = True;
} else {
isWithin = BusinessHours.isWithin(bh.id, targetTime);
}
Or rather a ternary operator for the cleanest code:
Boolean isWithin = !Test.isRunningTest() ? BusinessHours.isWithin(bh.id, targetTime) : true;

checking paragraph property loses the selection

in my vsto addin i have some simple code on a timer
private void MainTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (!dialogopen & Application.Documents.Count > 0)
{
var doc = Application.ActiveDocument;
Word.InlineShapes shps;
Word.Paragraphs pars;
try
{
pars = doc.Paragraphs;
}
catch (Exception)
{
return;
}
var pars2 = pars.Cast<Word.Paragraph>().ToList();
foreach (var obj in pars2)
{
if (obj.OutlineLevel == Word.WdOutlineLevel.wdOutlineLevelBodyText )//PROBLEM HERE
{
};
}
}
}
as soon as it reaches the line that checks the outlinelevel, even if i dont do a thing, the selection in the activedocument gets lost
of course the user cant use a plugin which keeps on canceling his selection...
googling didnt give me a thing
thanks
EDIT1
I tried making a static function for checking the styles, but it did not help. Here's the code
static public class Helpers
{
static public Word.Paragraph checkPars(List<Word.Paragraph> pars)
{
return pars.FirstOrDefault();//(x) => x.OutlineLevel == Word.WdOutlineLevel.wdOutlineLevelBodyText);
}
}
As you can see, I had to remove the actual check, since it was causing the cursor to blink and lose selection
please advise
We use the Application.ScreenUpdating = true; and this keep the selection for all properties in Paragraph except for the Range property.
Then, we tried to access the range via Reflection and this was the solution.
Range rng = (Range)typeof(Paragraph).GetProperty("Range").GetValue(comObj);
We tried to eliminate querying ActiveDocument thinking that that might have had side-effects that were causing the problem but that was not the case.
Then, we confirmed that the selection was not "lost" and screen-updating is the only problem, so we tried restoring the UI with Application.ScreenRefresh and while it did work, it causes the screen to flicker every time the timer fires and this is not good enough.
Finally, knowing that it's only a UI problem, I tried simply switching off Application.ScreenUpdating...
in ThisAddin
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Timer timer = new Timer(2000);
timer.Elapsed += (s, t) =>
{
var scrnUpdating = Application.ScreenUpdating;
Application.ScreenUpdating = false;
MainTimer.onElapsed(Application, t);
if (scrnUpdating)
Application.ScreenUpdating = true;
};
timer.Start();
}
In another class library (note that it's static, I still think this is the best way)...
public static class MainTimer
{
public static void onElapsed (Word.Application state, System.Timers.ElapsedEventArgs e)
{
if (state.Documents.Count > 0)
{
var doc = state.ActiveDocument;
Word.InlineShapes shps;
Word.Paragraphs pars;
try
{
pars = doc.Paragraphs;
}
catch (Exception)
{
return;
}
var pars2 = pars.Cast<Word.Paragraph>()
.Where(p => p.OutlineLevel == Word.WdOutlineLevel.wdOutlineLevelBodyText)
.Select(p => p) // do stuff with the selected parragraphs...
.ToList();
}
}
}
And this works for me.
The selection remains and is displayed in the UI without flicker.
I also eliminated some premature enumeration from your code: you don't meed the .ToList() before the foreach.

How to override action Email SalesOrder in SO30100 Screen

I try to customize action email in Salesorder screen, I use this code but it does not work. Could you give me some suggest about my code and customize send notification in Acumatica. I am using Acumatica 4.2.
Thank you in advance.
public CRActivityList<SOOrder> Activity;
public PXAction<SOOrder> notification;
[PXUIField(DisplayName = "Notifications", Visible = false)]
[PXButton(ImageKey = PX.Web.UI.Sprite.Main.DataEntryF)]
protected virtual IEnumerable Notification(PXAdapter adapter,
[PXString] string notificationCD
)
{
foreach (SOOrder order in adapter.Get<SOOrder>())
{
if (order.OrderType == "CM")
{
///my function
EmailNotification.Send_AtNPP(order, "SO301000", "SENDRETURNSO", "[[NoiDung]]", createEmailContent(order));
}
yield return order;
}
yield return adapter.Get();
}
What is the error you receive?
Have you tried removing the final yield? Last line can be
return adapter.Get();
I don't see why you would need the yield return order,
just do as suggested and return the adapter.
foreach (SOOrder order in adapter.Get<SOOrder>())
{
if (order.OrderType == "CM")
{
///my function
EmailNotification.Send_AtNPP(order, "SO301000", "SENDRETURNSO", "[[NoiDung]]", createEmailContent(order));
}
//yield return order;
}
return adapter.Get();

Is this a good pattern for PATCH

I am implementing a REST style API that allows an object to be PATCH'ed. The intention of the PATCH operation is to allow one or more properties in a class to be updated without touching an of the other properties that may be set.
The are examples of partial updates on the ServiceStack OrmLite page, but it seems to need hardcoding to indicate which fields will be partially updated. In my scenario it is upto the depend application to decide which fields to send.
I also have to cope with the scenario that the object may not have been persisted yet.
To get around this I have implemented the following:
public object Patch(Myclass request)
{
HttpStatusCode SuccessCode;
try
{
var result = (MyClass)Get(request);
if (result != null)
{
request.PopulateWithNonDefaultValues(result);
dbFactory.Run(dbCmd => dbCmd.UpdateNonDefaults(request, r => r.myId == request.myId));
}
else
{
dbFactory.Run(dbCmd => dbCmd.Save(request));
}
SuccessCode = HttpStatusCode.Accepted;
}
catch (Exception e)
{
log.Error(e);
SuccessCode = HttpStatusCode.InternalServerError;
}
return new HttpResult()
{
StatusCode = SuccessCode
};
}
It works, but something doesn't feel right, I'm sure there must be a better way?
That looks ok although you're code will be a lot shorter if you just throw let it throw C# Exceptions when there's an error and if you're inheriting from ServiceStack's New API base Service class you can use the already available Db property, e.g:
public object Patch(Myclass request)
{
var result = (MyClass)Get(request);
if (result != null)
{
request.PopulateWithNonDefaultValues(result);
Db.UpdateNonDefaults(request, r => r.myId == request.myId);
}
else
{
Db.Save(request);
}
return new HttpResult
{
StatusCode = HttpStatusCode.Accepted
};
}