Skip to content
September 6, 2012 / selenium34

Better Optional Elements

In yesterday’s post we discussed ways to allow Selenium to better handle items which may or may not have been on the page. We ended the post with something that might be considered a bit of a nuisance when attempting to utilize one of these non-located elements. Let’s take a look at the two tests we ended the post with:

@Test
public void ensureNullValue() {
  Assert.assertNull("A null value is expected for optional elements which do not exist on the page.", homePage.getOptionalIntroDivWithDefault());
}
@Test(expected = NoSuchElementException.class)
public void ensureNoSuchElementExceptionThrown() {
  homePage.getOptionalIntroDivWithDefault().getText();
}

Unfortunately the way proxies work in Java our proposed solution yesterday will not allow both of these two tests to pass. So, how can we ensure that the item is not located and retain the information from the NoSuchElementException?

Well, the easiest way is to create our own implementation of a WebElement. Here’s a portion of the class below:

public class MissingWebElement implements WebElement {
  private final NoSuchElementException nsee;
  public MissingWebElement(final NoSuchElementException nsee) {
    this.nsee = nsee;
  }
  @Override
  public void click() {
    throw nsee;
  }
  //Throw the NoSuchElementException for all methods the interface requires us to implement
}

It’s okay, you can admit it; you thought we were going to name that class CustomWebElement didn’t you?

Now we need to modify the CustomFieldDecorator to return a MissingWebElement when we have an optional item that was not located. We need to simply replace our decorate method from yesterday’s post, to what is shown below:

@Override
public Object decorate(final ClassLoader loader, final Field field) {
  if (!(WebElement.class.isAssignableFrom(field.getType()) || isDecoratableList(field))) {
    return null;
  }
  final CustomElementLocator locator = (CustomElementLocator) factory.createLocator(field);
  if (locator == null) {
    return null;
  }
  if (WebElement.class.isAssignableFrom(field.getType())) {
    final WebElement proxy = proxyForLocator(loader, locator);
    try {
      proxy.isDisplayed();
      return proxy;
    } catch (final NoSuchElementException nsee) {
      if (!locator.isOptionalElement()) {
        throw nsee;
      }
      return new MissingWebElement(nsee);
    }
  } else if (List.class.isAssignableFrom(field.getType())) {
    return proxyForListLocator(loader, locator);
  } else {
   return null;
  }
}

We now instruct our test to expect to receive a MissingWebElement:

@Test
public void ensureMissingElement() {
  Assert.assertTrue("A MissingWebElement is expected for optional elements which do not exist on the page.", homePage.getOptionalIntroDivWithDefault() instanceof MissingWebElement);
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: