Vishal Singh Sachan
Vishal Singh Sachan

Reputation: 21

Series of Multiple Actions in webdriver

I am just trying to enter a text in capital letters using set of keyboard actions. Here code using interface 'Action':

WebElement element = driver.findElement(By.id("email")); 
Actions builder = new Actions(driver); 
Action act = builder.moveToElement(element)
                    .keyDown(element,Keys.SHIFT)
                    .sendKeys("vishal")
                    .keyUp(Keys.SHIFT)
                    .build();
act.perform();

Above is working fine.

But if we do not use interface, it is not working why ??? Though this is executing fine but not performing the task. I think both should work.

WebElement element = driver.findElement(By.id("email")); 
Actions builder = new Actions(driver);
builder.moveToElement(element)
       .keyDown(element,Keys.SHIFT)
       .sendKeys("vishal")
       .keyUp(Keys.SHIFT)
       .build();
builder.perform();

Upvotes: 2

Views: 4906

Answers (3)

Sujay
Sujay

Reputation: 139

builder.moveToElement(element)
       .keyDown(element,Keys.SHIFT)
       .sendKeys("vishal")
       .keyUp(Keys.SHIFT)
       .build().perform();

Upvotes: 0

Jeremiah
Jeremiah

Reputation: 1145

In your second example, it's because you're calling build() then perform()

If you look at the Actions class implementations of those two methods:

  /**
   * Generates a composite action containing all actions so far, ready to be performed (and
   * resets the internal builder state, so subsequent calls to build() will contain fresh
   * sequences).
   *
   * @return the composite action
   */
  public Action build() {
    CompositeAction toReturn = action;
    resetCompositeAction();
    return toReturn;
  }

  /**
   * A convenience method for performing the actions without calling build() first.
   */
  public void perform() {
    build().perform();
  }

When you call build() it actually resets the internal state of the builder!

After that when you call perform() it rebuilds an empty object reference which has no behavior defined.

To correct the problem, I suggest replacing your call to build() with a call to perform() as shown below.

 WebElement element = driver.findElement(By.id("email")); 
 Actions builder = new Actions(driver);
 builder.moveToElement(element).keyDown(element, Keys.SHIFT).sendKeys("vishal").keyUp(Keys.SHIFT).perform();

I would expect that to do what you want, based on the implementation.

My investigation was done against selenium v 2.53.0

Upvotes: 2

krokodilko
krokodilko

Reputation: 36087

Because Actions#build() method resets a state of itself before returning the action,
see the implementation here: http://grepcode.com/file/repo1.maven.org/maven2/org.seleniumhq.selenium/selenium-api/2.18.0/org/openqa/selenium/interactions/Actions.java#Actions.build%28%29

338
339  public Action More ...build() {
340    CompositeAction toReturn = action;
341    resetCompositeAction();
342    return toReturn;
343  }

Pay attention to resetCompositeAction(); call - it resets the builder.

If you perform this:

 builder............
        ........ ().build();
builder.perform();

Then build() returns the action and resets a state of builder object.
Then if you call builder.perform(), it's do nothing.

Upvotes: 0

Related Questions