7

I am trying to automate Salesforce lightning using Selenium, but getting issues with identifying elements. Reason, its having dynamic IDs , and other attributes are either very long , or they are not unique.

For eg ,

<a id="170:1968;a" class="textUnderline outputLookupLink slds-truncate forceOutputLookup" 
data-refid="recordId" 
data-recordid="0059E000001aOCSQA2" 
data-special-link="true" 
href="#/sObject/0059E000001aOCSQA2/view" 
target="_blank" rel="noreferrer" 
title="" data-aura-rendered-by="170:1968;a" data-aura-class="forceOutputLookup"/>

In above code , ID is dynamic , Class is not unique, and all the Lookup elements are associated with it. Also the absolute path is not much trusted , and hence I am trying to find any concrete option to handle these elements. Any help will be highly appreciated.

  • 3
    I see this question has a couple of off-topic close votes. While Selenium isn't built by Salesforce, we all need to test and Selenium is a common tool to use for that. I'd like to hear what strategies people have found work best so would like this question to stay open. – Keith C Sep 5 '17 at 7:13
  • @KeithC I'd agree with you on that. – Dave Humm Sep 5 '17 at 8:17
3

In salesforce lightning we can define local ids, which may or may not be unique, depending upon how you are defining that. We can also add some fixed prefix or suffix with salesforce generated global ids to uniquely identifying the elements.

Excerpts from Salesforce Lightning Components Developers guide:

Local IDs A local ID is an ID that is only scoped to the component. A local ID is often unique but it’s not required to be unique. Create a local ID by using the aura:id attribute. For example: Note: aura:id doesn't support expressions. You can only assign literal string values to aura:id.

Find the button component by calling cmp.find("button1") in your client-side controller, where cmp is a reference to the component containing the button. find() returns different types depending on the result. • If the local ID is unique, find() returns the component. • If there are multiple components with the same local ID, find() returns an array of the components. • If there is no matching local ID, find() returns undefined. To find the local ID for a component in JavaScript, use cmp.getLocalId().

Global IDs Every component has a unique globalId, which is the generated runtime-unique ID of the component instance. A global ID (1) is not guaranteed to be the same beyond the lifetime of a component, so it should never be relied on. A global ID can be useful to differentiate between multiple instances of a component or for debugging purposes. To create a unique ID for an HTML element, you can use the globalId as a prefix or suffix for your element. For example: In your browser’s developer console, retrieve the element using document.getElementById("_footer"),where is the generated runtime-unique ID. To retrieve a component’s global ID in JavaScript, use the getGlobalId() function.
var globalId = cmp.getGlobalId();

| improve this answer | |
  • @slQh - As per my understanding , we can modify the ids like <id="170:1968;a;SomeUniqueText"> – AbhishekTiwari Sep 6 '17 at 7:31
  • @Abhishek Tiwari, edited my answer to add some example. – sIQh Sep 6 '17 at 12:08
  • Thanks mate , but unfortunately developers are using Standard pages , and there is no option to customise them. :( – AbhishekTiwari Sep 7 '17 at 12:34
  • Look at your source code of your page and try to build up some XPATH logic to find out the required elements then. – sIQh Sep 7 '17 at 12:37
  • Yes, somehow I am using label name and then following sibling, it's working . – AbhishekTiwari Sep 8 '17 at 13:24
0

If you could send HTML code it will be better to give you a proper xpath because Usually in this case you need to find the elements that are around this but have stable properties like labels and all. Those elements could be parent or child or sibling of this element First find the surrounding element using xpath and then trace back to this element. It may be bit of the work but your test cases will be reliable and will not be flaky. There are tons of examples in Google to write xpath using parent or sibling.check out.

| improve this answer | |
0

Below sharing a script that creates an opportunity in Salesforce lightning. I used some places JavascriptExecutor to click some components in here.

package BaseScripts; import org.testng.annotations.Test; import org.testng.annotations.; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.; import javax.swing.text.html.HTMLDocument.Iterator; import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.ie.InternetExplorerDriver; import org.testng.annotations.Test; import org.testng.annotations.; import org.testng.annotations.;

public class LightningTest {

protected static WebDriver driver;

@Test
public static void ChromeTestLighning() throwInterruptedException {

    //basic setup steps to kick off URL in  Chrome
    driver =  new ChromeDriver();
    driver.manage().timeouts().implicitlyWait(100, TimeUnit.SECONDS );
    driver.manage().timeouts().pageLoadTimeout(100, TimeUnit.SECONDS);
    driver.get("https://login.salesforce.com");
    driver.manage().window().maximize();

    //login to Salesforce
    driver.findElement(By.cssSelector("#username")).sendKeys("yourusername");
    driver.findElement(By.cssSelector("#password")).sendKeys("yourpassword");
    driver.findElement(By.cssSelector("#Login")).click();

    // Basic clicks in new navigation to Salesforce Lightning
    driver.findElement(By.xpath("//nav[contains(@class,'appLauncher')]//button")).click();
    ((JavascriptExecutor) driver).executeScript(     "arguments[0].click();",     driver.findElement(By.xpath("//button[text()='View All']")));
    ((JavascriptExecutor) driver).executeScript(     "arguments[0].click();",     driver.findElement(By.xpath("//a[@data-label='Opportunities']")));
    ((JavascriptExecutor) driver).executeScript(     "arguments[0].click();",     driver.findElement(By.xpath("//span[@class='slds-truncate'][contains(text(),'Opportunities')]")));
    ((JavascriptExecutor) driver).executeScript(     "arguments[0].click();",     driver.findElement(By.xpath("//div[@class='slds-truncate']")) );

    // Opportunity creation in Lightning
    driver.findElement(By.cssSelector("input[id$='a']")).sendKeys("23");
    driver.findElement(By.xpath("//div[@class='uiInput uiInputCheckbox uiInput--default uiInput--checkbox']//input")).click();
    driver.findElement(By.xpath("//a[@class='datePicker-openIcon display']")).click();
    driver.findElement(By.xpath("//button[@class='today slds-button slds-align_absolute-center slds-text-link']")).click();
    driver.findElement(By.xpath("//div[contains(@class,'full forcePageBlock forceRecordLayout')]//div[1]//div[1]//div[1]//div[3]//div[1]//div[1]//div[1]//div[1]//input[1]")).sendKeys("Third Opp");
    driver.findElement(By.xpath("//div[@class='uiMenu uiInput uiInputSelect forceInputPicklist uiInput--default uiInput--select']//div[@class='uiPopupTrigger']//div//div//a[@class='select']")).click();
    driver.findElement(By.xpath("//a[contains(text(),'Negotiation')]")).click();
    driver.findElement(By.xpath("//button[@class='slds-button slds-button--neutral uiButton--brand uiButton forceActionButton']//span[contains(@class,'label bBody')]")).click();
    String str = driver.getCurrentUrl();
    System.out.println(str);

    //Stop the browser to close before you can see things went fine.
    Thread.sleep(20000);
    driver.quit();         
}

}

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.