Тестирование эффекта AJAX/POST на странице с селеном - элемент не найден

Это может быть похоже на 5660956, но я делаю GET сначала...

Я думаю, что ключ здесь - Selenium, отсюда и теги. На всякий случай это важно: я работаю на Java, использую NinjaFramewor, FluentLenium и Firefox. Он работает локально, но также и на блоке CI без головы с Xvfb. У меня есть несколько тестов FluentLenium, так что все не сломано!

У меня есть веб-страница с простой формой входа в систему, которая выполняет вызов JavaScript, который выполняет AJAX POST. Ответ AJAX перехватывается JavaScript и вызывает обновление части тела страницы с различными результатами для входа в систему, регистрации и сбоя. Я вижу, что это происходит, когда я тестирую вручную, и даже когда я запускаю эти тесты локально.

Тест выглядит так:

import org.fluentlenium.adapter.util.SharedDriver;
import org.fluentlenium.core.annotation.Page;
import org.junit.Test;

@SharedDriver(deleteCookies=true)
public class UserControllerTest extends JSTest {

  @Page
  HomePage home;
  @Page 
  LoginPage login;

  @Test
  public void test_cantLoginUntilReg() {
    goTo(login);
    login.fillOutReg("test_cantLoginUntilReg");
    login.chooseLogin();    // script that POSTS and does AJAX update
    login.isErrorResult();  // errors
    goTo(login);
    login.fillOutReg("test_cantLoginUntilReg");
    login.chooseRegister();   // script that POSTS and does AJAX update
    login.isWelcomeResult();  // errors
    login.chooseHome();       // GET on home
    home.isLoggedIn();        // this works
}

// more tests
}

И LoginPage, где у меня возникли проблемы (супер класс, содержащий константы, сложенные обратно):

public class LoginPage extends FluentPage {

  protected static final String HOME_PAGE = "http://localhost:8080";
  private static final String PAGE = HOME_PAGE + "/login";

  @AjaxElement
  FluentWebElement welcomeDiv;
  @AjaxElement
  FluentWebElement errorDiv;

  @Override
  public String getUrl() {
    return PAGE;
  }

  @Override
  public void isAt() {
    assertTrue("url is " + url(), url().contains("login"));
    assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Login"));
    assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Register"));
  }

  public void isErrorResult() {
   assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Failed"));
   assertNull("cookie is " + getCookie(SESSION_COOKIE_NAME), getCookie(SESSION_COOKIE_NAME));
 }

  public void fillOutReg(String testName) {
    fill("#email").with(testName + "@UserControllerJSTests.test.com"); // this passes the minimal validation in place so far
    fill("#password").with("reallyBadPassword");
    fill("#identName").with(testName);  
  }

  public void chooseLogin() {
    executeScript(LOGIN_SCRIPT); // I'd prefer click on the form, but that seemed to be a source of trouble as well
  }

// and so on
}

Метод isErrorResult() никогда не выполняется! Поиск h1 показывает, что текст h1 остается таким же, каким он был при первой загрузке страницы. Очистка cookie сеанса показывает различное поведение на разных машинах (вероятно, нужно что-то ждать). Я также пытался протестировать содержимое welcomeDiv. У меня есть чувство, что я должен быть в состоянии использовать @AjaxElement, чтобы помочь здесь, но я не совсем понял, как.

Я не хочу проверять возвращение JSON. У меня есть тесты, в которых не участвует Selenium, которые уже достаточно близки к этому.

Что я хочу сделать, так это автоматизировать проверку того, что пользователь увидит правильную вещь в конце браузера после POST. Даже если есть обходной путь для этого кода, другие функции будут иметь достаточно большие загрузки, что GET действительно не имеет смысла; и тестируемый AJAX кажется разумным желанием.

Есть идеи, пожалуйста?

1 ответ

У меня есть рабочее решение. Как всегда, сочетание изменений привело меня в то место, где я хочу быть. В грубом порядке важности я думаю, что они:

  • Запрашивать состояние @Page можно только один раз в любом тесте. Первый тест контента Ajaxed выиграл. Последующие нашли неправильное значение.
  • Выполнение вызова assert для проверки того, что элемент ajax - это то, что должно быть из тестового объекта, а не внутри объекта страницы. Неработающая версия закомментирована в приведенном ниже коде, так как это было неожиданно.
  • Использование @AjaxElement, а затем запрос содержимого этих элементов.
  • На одной веб-странице отсутствовал тег id для элемента, который я искал (не учитывал бы все проблемы).
  • Среди других небольших изменений по пути я сейчас тестирую заголовочные элементы h1 и элементы списка, а не div, который их содержит; и разные версии h1 имеют разные значения идентификатора. Не (пока) регрессия проверила, насколько это важно.

Тестовый код теперь:

import org.fluentlenium.adapter.util.SharedDriver;
import org.fluentlenium.core.annotation.Page; 
import static org.junit.Assert.assertTrue;
import org.junit.Test;

@SharedDriver(deleteCookies=true)
public class UserControllerTest extends JSTest {

 @Page
 HomePage home;
 @Page 
 LoginPage login;

 @Test
 public void test_cantLoginBeforeReg() {
    // try to login without being registered
    goTo(login);
    login.fillOutReg("test_cantLoginUntilReg");
    login.chooseLogin();
    isErrorResult();
    goTo(home);
    home.isNotLoggedIn();
 }

 @Test
 public void test_registerLogout() {
    goTo(login);
    login.fillOutReg("test_registerLogout");
    login.chooseRegister();
    isWelcomeResult();
    login.chooseLogout();
    home.isAt();
    home.isNotLoggedIn();
 }

// tests etc

 public void isWelcomeResult() {
    assertTrue(login.getWelcomeText(), login.getWelcomeText().contains("Welcome"));
 }
 public void isErrorResult() {
    assertTrue(login.getErrorText(), login.getErrorText().contains("Failed"));
 }
}

И класс страницы:

import org.fluentlenium.core.annotation.AjaxElement;
import org.fluentlenium.core.domain.FluentWebElement;
import static org.junit.Assert.assertTrue;

public class LoginPage extends TripVisPage {

private static final String PAGE = HOME_PAGE + "/login";

@AjaxElement
FluentWebElement welcomeHeading;
@AjaxElement
FluentWebElement errorHeading;

@Override
public String getUrl() {
  return PAGE;
}

public String getWelcomeText() {
  return welcomeHeading.getText();
}

public String getErrorText() {
  return errorHeading.getText();
}

@Override
public void isAt() {
  assertTrue("url is " + url(), url().contains("login"));
  assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Login"));
  assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Register"));
}
/* calling these from the test is broken
public void isWelcomeResult() {
  assertTrue(getWelcomeText(), getWelcomeText().contains("Welcome"));
}
public void isErrorResult() {
  assertTrue(getErrorText(), getErrorText().contains("Failed"));
}
*/
public void fillOutReg(String testName) {
  fill("#email").with(testName + "@UserControllerJSTests.tripvis.co.uk");
  fill("#password").with("reallyBadPassword");
  fill("#identName").with(testName);    
}

public void chooseAbout() {
  click(LINK_ABOUT_ID);
}

public void chooseLegal() {
  click(LINK_LEGAL_ID);
}

public void chooseRegister() {
  executeScript(REGISTER_SCRIPT);
}

public void chooseLogin() {
  executeScript(LOGIN_SCRIPT);
}

public void chooseLogout() {
  click(LINK_LOGOUT_ID);
}
}
Другие вопросы по тегам