2012-09-25 10 views
9

Scenario: modificare e salvare un cambiamento incompleta ad una campagnaCome rendere Behat attendere una chiamata AJAX?

Given I click on the Campaign section folder 
And I press Save in the selected Campaign 
Then I should see an error balloon informing the changes cannot be saved 

punto è che questo 'palloncino errore' nella fase finale è una chiamata Ajax che poi portare un palloncino verde o rosso a seconda del successo di l'operazione. Attualmente quello che faccio è dopo 'E premo Salva ...' Farò un sonno (3) per dargli il tempo di mostrare questo pallone. Questo non sembra molto intelligente perché stai perdendo tempo e anche perché a volte può essere necessario più o meno tempo per elaborare questa chiamata.

Come fate i vostri test Behat, aspettate che Ajax sia fatto invece di mettere le bestie a dormire?

grazie mille per qualsiasi feedback!

+0

mostrare un po 'di codice? – StaticVariable

risposta

26

Questo viene fatto aspettando che le vostre chiamate ajax in sospeso raggiungano 0. jQuery.active controllerà solo quello per voi.

Nel tuo FeatureContext.php, puoi fare qualcosa del tipo;

public function iShouldSeeAnErrorBalloon($title) 
{ 
    $time = 5000; // time should be in milliseconds 
    $this->getSession()->wait($time, '(0 === jQuery.active)'); 
    // asserts below 
} 

E assicurarsi di utilizzare un driver Mink che corre Javascript e Ajax (il default non lo fa).

1

Nel caso in cui si utilizza Prototypejs (es Magento), il codice equivalente è:

public function iShouldSeeAnErrorBalloon($title) 
{ 
    $this->getSession()->wait($duration, '(0 === Ajax.activeRequestCount)'); 
    // asserts below 
} 
+1

da dove proviene la variabile $ duration? –

+0

http://mink.behat.org/api/behat/mink/session.html#wait() 'vuoto pubblico attesa (tempo intero, condizione stringa) Attende un po 'di tempo o fino a quando la condizione JS diventa vera. – Steff

+0

Solo aggiornando quel collegamento, anche se come ho usato i numeri di linea sarà senza dubbio presto fuori moda: https://github.com/Behat/Mink/blob/master/src/Behat/Mink/Session.php # L318-L329 – DanielM

2

lo faccio aspettando il DOM per cambiare a seguito della chiamata Ajax. Ho fatto una sottoclasse di DocumentElement, definendolo AsyncDocumentElement e l'override del metodo findAll:

public function findAll($selector, $locator, $waitms=5000) 
{ 
    $xpath = $this->getSession()->getSelectorsHandler()->selectorToXpath($selector, $locator); 

    // add parent xpath before element selector 
    if (0 === strpos($xpath, '/')) { 
     $xpath = $this->getXpath().$xpath; 
    } else { 
     $xpath = $this->getXpath().'/'.$xpath; 
    } 

    $page = $this->getSession()->getPage(); 

    // my code to wait until the xpath expression provides an element 
    if ($waitms && !($this->getSession()->getDriver() instanceof \Behat\Symfony2Extension\Driver\KernelDriver)) { 
     $templ = 'document.evaluate("%s", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength > 0;'; 

     $waitJs = sprintf($templ, $xpath); 

     $this->getSession()->wait($waitms, $waitJs); 
    } 

    return $this->getSession()->getDriver()->find($xpath); 
} 

Poi, nel \ Behat \ visone \ Session ho cambiato il costruttore di utilizzare quella classe.

public function __construct(DriverInterface $driver, SelectorsHandler $selectorsHandler = null) 
{ 
    $driver->setSession($this); 

    if (null === $selectorsHandler) { 
     $selectorsHandler = new SelectorsHandler(); 
    } 

    $this->driver   = $driver; 
    $this->page    = new AsyncDocumentElement($this); 
    $this->selectorsHandler = $selectorsHandler; 
} 

Una volta eseguita questa operazione, ho trovato che i miei test AngularJS funzionavano. Finora, ho provato solo su Firefox.