From 63216e0f95dd88a74cd0d019bb0d9b2b429428ea Mon Sep 17 00:00:00 2001
From: Demian Katz <demian.katz@villanova.edu>
Date: Wed, 4 Nov 2015 14:39:00 -0500
Subject: [PATCH] Refactored Mink tests to work w/ Selenium or Zombie.js.

---
 .../src/VuFindTest/Unit/MinkTestCase.php      | 122 +++++++--
 .../src/VuFindTest/Unit/UserCreationTrait.php |  15 +-
 .../VuFindTest/Mink/AdvancedSearchTest.php    |  55 ++--
 .../src/VuFindTest/Mink/BasicTest.php         |   9 +-
 .../src/VuFindTest/Mink/CartTest.php          | 124 +++------
 .../src/VuFindTest/Mink/FavoritesTest.php     | 247 ++++++++----------
 .../src/VuFindTest/Mink/RecordActionsTest.php | 206 +++++++--------
 .../src/VuFindTest/Mink/RecordTest.php        |  33 +--
 8 files changed, 406 insertions(+), 405 deletions(-)

diff --git a/module/VuFind/src/VuFindTest/Unit/MinkTestCase.php b/module/VuFind/src/VuFindTest/Unit/MinkTestCase.php
index 6bd9d8deb10..455e1af1842 100644
--- a/module/VuFind/src/VuFindTest/Unit/MinkTestCase.php
+++ b/module/VuFind/src/VuFindTest/Unit/MinkTestCase.php
@@ -28,6 +28,7 @@
  */
 namespace VuFindTest\Unit;
 use Behat\Mink\Driver\ZombieDriver, Behat\Mink\Session,
+    Behat\Mink\Element\Element,
     VuFind\Config\Locator as ConfigLocator,
     VuFind\Config\Writer as ConfigWriter;
 
@@ -43,18 +44,18 @@ use Behat\Mink\Driver\ZombieDriver, Behat\Mink\Session,
 abstract class MinkTestCase extends DbTestCase
 {
     /**
-     * Mink driver
+     * Modified configurations
      *
-     * @var ZombieDriver
+     * @var array
      */
-    protected static $driver = false;
+    protected $modifiedConfigs;
 
     /**
-     * Modified configurations
+     * Mink session
      *
-     * @var array
+     * @var Session
      */
-    protected $modifiedConfigs;
+    protected $session;
 
     /**
      * Reconfigure VuFind for the current test.
@@ -103,6 +104,59 @@ abstract class MinkTestCase extends DbTestCase
         $writer->save();
     }
 
+    /**
+     * Are we using the Zombie.js driver?
+     *
+     * @return bool
+     */
+    protected function isZombieDriver()
+    {
+        return getenv('VUFIND_MINK_DRIVER') !== 'selenium';
+    }
+
+    /**
+     * Assert an HTTP status code (if supported).
+     *
+     * @param int $code Expected status code.
+     *
+     * @return void
+     */
+    protected function assertHttpStatus($code)
+    {
+        // This assertion is not supported by Selenium.
+        if ($this->isZombieDriver()) {
+            $this->assertEquals(200, $this->getMinkSession()->getStatusCode());
+        }
+    }
+
+    /**
+     * Sleep if necessary.
+     *
+     * @param int $secs Seconds to sleep
+     *
+     * @return void
+     */
+    protected function snooze($secs = 1)
+    {
+        // Sleep is not necessary for Zombie.js.
+        if (!$this->isZombieDriver()) {
+            sleep($secs);
+        }
+    }
+
+    /**
+     * Test an element for visibility.
+     *
+     * @param Element $element Element to test
+     *
+     * @return bool
+     */
+    protected function checkVisibility(Element $element)
+    {
+        // Zombie.js does not support visibility checks; just assume true.
+        return $this->isZombieDriver() ? true : $element->isVisible();
+    }
+
     /**
      * Get the Mink driver, initializing it if necessary.
      *
@@ -110,14 +164,11 @@ abstract class MinkTestCase extends DbTestCase
      */
     protected function getMinkDriver()
     {
-        if (self::$driver === false) {
-            self::$driver = (getenv('VUFIND_MINK_DRIVER') === 'selenium')
-                ? new \Behat\Mink\Driver\Selenium2Driver('firefox')
-                : new ZombieDriver(
-                    new \Behat\Mink\Driver\NodeJS\Server\ZombieServer()
-                );
-        }
-        return self::$driver;
+        return !$this->isZombieDriver()
+            ? new \Behat\Mink\Driver\Selenium2Driver('firefox')
+            : new ZombieDriver(
+                new \Behat\Mink\Driver\NodeJS\Server\ZombieServer()
+            );
     }
 
     /**
@@ -127,7 +178,24 @@ abstract class MinkTestCase extends DbTestCase
      */
     protected function getMinkSession()
     {
-        return new Session($this->getMinkDriver());
+        if (empty($this->session)) {
+            $this->session = new Session($this->getMinkDriver());
+            $this->session->start();
+        }
+        return $this->session;
+    }
+
+    /**
+     * Shut down the Mink session.
+     *
+     * @return void
+     */
+    protected function stopMinkSession()
+    {
+        if (!empty($this->session)) {
+            $this->session->stop();
+            $this->session = null;
+        }
     }
 
     /**
@@ -168,6 +236,24 @@ abstract class MinkTestCase extends DbTestCase
         }
     }
 
+    /**
+     * Wait for an element to exist, then retrieve it.
+     *
+     * @param Element $page     Page element
+     * @param string  $selector CSS selector
+     * @param int     $timeout  Wait timeout (in ms)
+     *
+     * @return mixed
+     */
+    protected function findCss(Element $page, $selector, $timeout = 1000)
+    {
+        $session = $this->getMinkSession();
+        $session->wait($timeout, "$('$selector').length > 0");
+        $result = $page->find('css', $selector);
+        $this->assertTrue(is_object($result));
+        return $result;
+    }
+
     /**
      * Standard setup method.
      *
@@ -194,6 +280,7 @@ abstract class MinkTestCase extends DbTestCase
      */
     public function tearDown()
     {
+        $this->stopMinkSession();
         $this->restoreConfigs();
     }
 
@@ -204,9 +291,6 @@ abstract class MinkTestCase extends DbTestCase
      */
     public static function tearDownAfterClass()
     {
-        // Stop the Mink driver!
-        if (self::$driver !== false) {
-            self::$driver->stop();
-        }
+        // No teardown actions at this time.
     }
 }
diff --git a/module/VuFind/src/VuFindTest/Unit/UserCreationTrait.php b/module/VuFind/src/VuFindTest/Unit/UserCreationTrait.php
index e05c65bcbf8..b4b72079b2f 100644
--- a/module/VuFind/src/VuFindTest/Unit/UserCreationTrait.php
+++ b/module/VuFind/src/VuFindTest/Unit/UserCreationTrait.php
@@ -75,8 +75,7 @@ trait UserCreationTrait
      */
     protected function assertLightboxWarning(Element $page, $message)
     {
-        $warning = $page->find('css', '.modal-body .alert-danger .message');
-        $this->assertTrue(is_object($warning));
+        $warning = $this->findCss($page, '.modal-body .alert-danger .message');
         $this->assertEquals($message, $warning->getText());
     }
 
@@ -100,8 +99,7 @@ trait UserCreationTrait
         ];
 
         foreach ($defaults as $field => $default) {
-            $element = $page->findById('account_' . $field);
-            $this->assertNotNull($element);
+            $element = $this->findCss($page, '#account_' . $field);
             $element->setValue(
                 isset($overrides[$field]) ? $overrides[$field] : $default
             );
@@ -120,13 +118,11 @@ trait UserCreationTrait
     protected function fillInLoginForm(Element $page, $username, $password)
     {
         if (null !== $username) {
-            $usernameField = $page->find('css', '.modal-body [name="username"]');
-            $this->assertNotNull($usernameField);
+            $usernameField = $this->findCss($page, '.modal-body [name="username"]');
             $usernameField->setValue($username);
         }
         if (null !== $password) {
-            $passwordField = $page->find('css', '.modal-body [name="password"]');
-            $this->assertNotNull($passwordField);
+            $passwordField = $this->findCss($page, '.modal-body [name="password"]');
             $passwordField->setValue($password);
         }
     }
@@ -140,8 +136,7 @@ trait UserCreationTrait
      */
     protected function submitLoginForm(Element $page)
     {
-        $button = $page->find('css', '.modal-body .btn.btn-primary');
-        $this->assertNotNull($button);
+        $button = $this->findCss($page, '.modal-body .btn.btn-primary');
         $button->click();
     }
 
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/AdvancedSearchTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/AdvancedSearchTest.php
index 7d1c5a54bf8..52b0f061c73 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/AdvancedSearchTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/AdvancedSearchTest.php
@@ -52,58 +52,65 @@ class AdvancedSearchTest extends \VuFindTest\Unit\MinkTestCase
 
         // Go to the advanced search page
         $session = $this->getMinkSession();
-        $session->start();
         $path = '/Search/Advanced';
         $session->visit($this->getVuFindUrl() . $path);
         $page = $session->getPage();
 
         // Add a group
         $session->executeScript("addGroup()");
-        $this->assertNotNull($page->findById('group1'));
+        $this->snooze();
+        $this->findCss($page, '#group1');
 
         // Add a search term
         $session->executeScript("addSearch(0)"); // add_search_link_0 click
-        $this->assertNotNull($page->findById('search0_3'));
+        $this->snooze();
+        $this->findCss($page, '#search0_3');
         // No visible x next to lonely search term
-        $this->assertNotNull($page->find('css', '#search1_0 .close.hidden'));
+        $this->findCss($page, '#search1_0 .close.hidden');
         // Add a search term in another group
         $session->executeScript("addSearch(1)"); // add_search_link_1 click
-        $this->assertNotNull($page->findById('search1_1'));
+        $this->findCss($page, '#search1_1');
         // Visible x next to lonely search term
-        $this->assertNotNull($page->find('css', '#search1_0 .close:not(.hidden)'));
+        $this->findCss($page, '#search1_0 .close:not(.hidden)');
 
         // Enter search for bride of the tomb
-        $page->findById('search_lookfor0_0')->setValue('bride');
-        $page->findById('search_lookfor0_1')->setValue('tomb');
-        $page->findById('search_type0_1')->selectOption('Title');
-        $page->findById('search_lookfor0_2')->setValue('garbage');
-        $page->findById('search_lookfor0_3')->setValue('1883');
-        $page->findById('search_type0_3')->selectOption('year');
+        $this->findCss($page, '#search_lookfor0_0')->setValue('bride');
+        $this->findCss($page, '#search_lookfor0_1')->setValue('tomb');
+        $this->findCss($page, '#search_type0_1')->selectOption('Title');
+        $this->findCss($page, '#search_lookfor0_2')->setValue('garbage');
+        $this->findCss($page, '#search_lookfor0_3')->setValue('1883');
+        $this->findCss($page, '#search_type0_3')->selectOption('year');
 
         // Term removal
         $session->executeScript("deleteSearch(0, 2)"); // search0_2 x click
         $this->assertNull($page->findById('search0_3'));
         // Terms collapsing up
-        $this->assertEquals('1883', $page->findById('search_lookfor0_2')->getValue());
-        $this->assertEquals('year', $page->findById('search_type0_2')->getValue());
+        $this->assertEquals('1883', $this->findCss($page, '#search_lookfor0_2')->getValue());
+        $this->assertEquals('year', $this->findCss($page, '#search_type0_2')->getValue());
 
         // Submit search form
-        $page->find('css', '[type=submit]')->press();
+        $this->findCss($page, '[type=submit]')->press();
 
         // Check for proper search
         $this->assertEquals(
             '(All Fields:bride AND Title:tomb AND Year of Publication:1883)',
-            $page->find('css', '.adv_search_terms strong')->getText()
+            $this->findCss($page, '.adv_search_terms strong')->getHtml()
         );
 
         // Test edit search
-        $page->find('css', '.adv_search_links > a:first-child')->click();
-        $this->assertEquals('bride', $page->findById('search_lookfor0_0')->getValue());
-        $this->assertEquals('tomb',  $page->findById('search_lookfor0_1')->getValue());
-        $this->assertEquals('Title', $page->findById('search_type0_1')->getValue());
-        $this->assertEquals('1883',  $page->findById('search_lookfor0_2')->getValue());
-        $this->assertEquals('year',  $page->findById('search_type0_2')->getValue());
-
-        $session->stop();
+        $links = $page->findAll('css', '.adv_search_links a');
+        foreach ($links as $link) {
+            if ($this->checkVisibility($link)
+                && $link->getHtml() == 'Edit this Advanced Search'
+            ) {
+                $link->click();
+                break;
+            }
+        }
+        $this->assertEquals('bride', $this->findCss($page, '#search_lookfor0_0')->getValue());
+        $this->assertEquals('tomb',  $this->findCss($page, '#search_lookfor0_1')->getValue());
+        $this->assertEquals('Title', $this->findCss($page, '#search_type0_1')->getValue());
+        $this->assertEquals('1883',  $this->findCss($page, '#search_lookfor0_2')->getValue());
+        $this->assertEquals('year',  $this->findCss($page, '#search_type0_2')->getValue());
     }
 }
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/BasicTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/BasicTest.php
index a0b0c40d686..d4ca6722576 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/BasicTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/BasicTest.php
@@ -46,10 +46,9 @@ class BasicTest extends \VuFindTest\Unit\MinkTestCase
     public function testHomePage()
     {
         $session = $this->getMinkSession();
-        $session->start();
-        $session->visit($this->getVuFindUrl());
-        $this->assertEquals(200, $session->getStatusCode());
-        $this->assertTrue(false !== strstr($session->getPage()->getContent(), 'VuFind'));
-        $session->stop();
+        $session->visit($this->getVuFindUrl() . '/Search/Home');
+        $this->assertHttpStatus(200);
+        $page = $session->getPage();
+        $this->assertTrue(false !== strstr($page->getContent(), 'VuFind'));
     }
 }
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CartTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CartTest.php
index 3067c54609c..8ce767a355b 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CartTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CartTest.php
@@ -27,7 +27,6 @@
  */
 namespace VuFindTest\Mink;
 use Behat\Mink\Element\Element;
-use Behat\Mink\Session;
 
 /**
  * Mink cart test class.
@@ -55,12 +54,11 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
     /**
      * Get a reference to a standard search results page.
      *
-     * @param Session $session Mink session
-     *
      * @return Element
      */
-    protected function getSearchResultsPage(Session $session)
+    protected function getSearchResultsPage()
     {
+        $session = $this->getMinkSession();
         $path = '/Search/Results?lookfor=id%3A(testsample1+OR+testsample2)';
         $session->visit($this->getVuFindUrl() . $path);
         return $session->getPage();
@@ -81,7 +79,7 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
         // completely failing.
         for ($clickRetry = 0; $clickRetry <= 4; $clickRetry++) {
             $updateCart->click();
-            $content = $page->find('css', '.popover-content');
+            $content = $this->findCss($page, '.popover-content');
             if (is_object($content)) {
                 $this->assertEquals(
                     'No items were selected. '
@@ -128,11 +126,9 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
      * into the cart, then opening the lightbox so that additional actions may
      * be attempted.
      *
-     * @param Session $session Mink session
-     *
      * @return Element
      */
-    protected function setUpGenericCartTest(Session $session)
+    protected function setUpGenericCartTest()
     {
         // Activate the cart:
         $this->changeConfigs(
@@ -141,16 +137,15 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
             ]
         );
 
-        $page = $this->getSearchResultsPage($session);
+        $page = $this->getSearchResultsPage();
 
         // Click "add" without selecting anything.
-        $updateCart = $page->find('css', '#updateCart');
-        $this->assertTrue(is_object($updateCart));
+        $updateCart = $this->findCss($page, '#updateCart');
         $this->tryAddingNothingToCart($page, $updateCart);
 
         // Now actually select something:
         $this->addCurrentPageToCart($page, $updateCart);
-        $this->assertEquals('2', $page->find('css', '#cartItems strong')->getText());
+        $this->assertEquals('2', $this->findCss($page, '#cartItems strong')->getText());
 
         // Open the cart and empty it:
         $this->openCartLightbox($page);
@@ -167,8 +162,7 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
      */
     protected function checkEmptyCart(Element $page)
     {
-        $info = $page->find('css', '.modal-body .form-inline .alert-info');
-        $this->assertTrue(is_object($info));
+        $info = $this->findCss($page, '.modal-body .form-inline .alert-info');
         $this->assertEquals('Your Book Bag is empty.', $info->getText());
     }
 
@@ -182,8 +176,7 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
      */
     protected function checkForNonSelectedMessage(Element $page)
     {
-        $warning = $page->find('css', '.modal-body .alert .message');
-        $this->assertTrue(is_object($warning));
+        $warning = $this->findCss($page, '.modal-body .alert .message');
         $this->assertEquals(
             'No items were selected. '
             . 'Please click on a checkbox next to an item and try again.',
@@ -229,11 +222,8 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testFillAndDeleteFromCart()
     {
-        $session = $this->getMinkSession();
-        $session->start();
-        $page = $this->setUpGenericCartTest($session);
-        $delete = $page->findById('cart-delete-label');
-        $this->assertTrue(is_object($delete));
+        $page = $this->setUpGenericCartTest();
+        $delete = $this->findCss($page, '#cart-delete-label');
 
         // First try deleting without selecting anything:
         $delete->click();
@@ -242,19 +232,17 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
         // Now actually select the records to delete:
         $this->selectAllItemsInCart($page);
         $delete->click();
-        $deleteConfirm = $page->find('css', '#cart-confirm-delete');
-        $this->assertTrue(is_object($deleteConfirm));
+        $deleteConfirm = $this->findCss($page, '#cart-confirm-delete');
         $deleteConfirm->click();
         $this->checkEmptyCart($page);
 
         // Close the lightbox:
-        $close = $page->find('css', 'button.close');
+        $close = $this->findCss($page, 'button.close');
         $close->click();
 
         // Confirm that the cart has truly been emptied:
-        $this->assertEquals('0', $page->find('css', '#cartItems strong')->getText());
-
-        $session->stop();
+        $this->snooze(); // wait for display to update
+        $this->assertEquals('0', $this->findCss($page, '#cartItems strong')->getText());
     }
 
     /**
@@ -265,27 +253,22 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testFillAndEmptyCart()
     {
-        $session = $this->getMinkSession();
-        $session->start();
-        $page = $this->setUpGenericCartTest($session);
+        $page = $this->setUpGenericCartTest();
 
         // Activate the "empty" control:
-        $empty = $page->findById('cart-empty-label');
-        $this->assertTrue(is_object($empty));
+        $empty = $this->findCss($page, '#cart-empty-label');
         $empty->click();
-        $emptyConfirm = $page->find('css', '#cart-confirm-empty');
-        $this->assertTrue(is_object($emptyConfirm));
+        $emptyConfirm = $this->findCss($page, '#cart-confirm-empty');
         $emptyConfirm->click();
         $this->checkEmptyCart($page);
 
         // Close the lightbox:
-        $close = $page->find('css', 'button.close');
+        $close = $this->findCss($page, 'button.close');
         $close->click();
 
         // Confirm that the cart has truly been emptied:
-        $this->assertEquals('0', $page->find('css', '#cartItems strong')->getText());
-
-        $session->stop();
+        $this->snooze(); // wait for display to update
+        $this->assertEquals('0', $this->findCss($page, '#cartItems strong')->getText());
     }
 
     /**
@@ -295,11 +278,8 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testCartEmail()
     {
-        $session = $this->getMinkSession();
-        $session->start();
-        $page = $this->setUpGenericCartTest($session);
-        $button = $page->find('css', '.cart-controls button[name=email]');
-        $this->assertTrue(is_object($button));
+        $page = $this->setUpGenericCartTest();
+        $button = $this->findCss($page, '.cart-controls button[name=email]');
 
         // First try clicking without selecting anything:
         $button->click();
@@ -308,20 +288,18 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
         // Now do it for real -- we should get a login prompt.
         $this->selectAllItemsInCart($page);
         $button->click();
-        $title = $page->find('css', '#modalTitle');
+        $title = $this->findCss($page, '#modalTitle');
         $this->assertEquals('Email Selected Book Bag Items', $title->getText());
         $this->checkForLoginMessage($page);
 
         // Create an account.
-        $page->find('css', '.modal-body .createAccountLink')->click();
+        $this->findCss($page, '.modal-body .createAccountLink')->click();
         $this->fillInAccountForm($page);
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
 
         // Test that we now have an email form.
-        $toField = $page->findById('email_to');
+        $toField = $this->findCss($page, '#email_to');
         $this->assertNotNull($toField);
-
-        $session->stop();
     }
 
     /**
@@ -331,11 +309,8 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testCartSave()
     {
-        $session = $this->getMinkSession();
-        $session->start();
-        $page = $this->setUpGenericCartTest($session);
-        $button = $page->find('css', '.cart-controls button[name=saveCart]');
-        $this->assertTrue(is_object($button));
+        $page = $this->setUpGenericCartTest();
+        $button = $this->findCss($page, '.cart-controls button[name=saveCart]');
 
         // First try clicking without selecting anything:
         $button->click();
@@ -344,7 +319,7 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
         // Now do it for real -- we should get a login prompt.
         $this->selectAllItemsInCart($page);
         $button->click();
-        $title = $page->find('css', '#modalTitle');
+        $title = $this->findCss($page, '#modalTitle');
         $this->assertEquals('Save Selected Book Bag Items', $title->getText());
         $this->checkForLoginMessage($page);
 
@@ -353,22 +328,17 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
         $this->submitLoginForm($page);
 
         // Save the favorites.
-        $submit = $page->find('css', '.modal-body input[name=submit]');
-        $this->assertTrue(is_object($submit));
+        $submit = $this->findCss($page, '.modal-body input[name=submit]');
         $submit->click();
-        $result = $page->find('css', '.modal-body .alert-info');
-        $this->assertTrue(is_object($result));
+        $result = $this->findCss($page, '.modal-body .alert-info');
         $this->assertEquals(
             'Your item(s) were saved successfully', $result->getText()
         );
 
         // Click the close button.
-        $submit = $page->find('css', '.modal-body .btn');
-        $this->assertTrue(is_object($submit));
+        $submit = $this->findCss($page, '.modal-body .btn');
         $this->assertEquals('close', $submit->getText());
         $submit->click();
-
-        $session->stop();
     }
 
     /**
@@ -378,11 +348,8 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testCartExport()
     {
-        $session = $this->getMinkSession();
-        $session->start();
-        $page = $this->setUpGenericCartTest($session);
-        $button = $page->find('css', '.cart-controls button[name=export]');
-        $this->assertTrue(is_object($button));
+        $page = $this->setUpGenericCartTest();
+        $button = $this->findCss($page, '.cart-controls button[name=export]');
 
         // First try clicking without selecting anything:
         $button->click();
@@ -391,23 +358,18 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
         // Now do it for real -- we should get an export option list:
         $this->selectAllItemsInCart($page);
         $button->click();
-        $title = $page->find('css', '#modalTitle');
+        $title = $this->findCss($page, '#modalTitle');
         $this->assertEquals('Export Selected Book Bag Items', $title->getText());
 
         // Select EndNote option
-        $select = $page->find('css', '#format');
-        $this->assertTrue(is_object($select));
+        $select = $this->findCss($page, '#format');
         $select->selectOption('EndNote');
 
         // Do the export:
-        $submit = $page->find('css', '.modal-body input[name=submit]');
-        $this->assertTrue(is_object($submit));
+        $submit = $this->findCss($page, '.modal-body input[name=submit]');
         $submit->click();
-        $result = $page->find('css', '.modal-body .alert .text-center .btn');
-        $this->assertTrue(is_object($result));
+        $result = $this->findCss($page, '.modal-body .alert .text-center .btn');
         $this->assertEquals('Download File', $result->getText());
-
-        $session->stop();
     }
 
     /**
@@ -418,10 +380,8 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
     public function testCartPrint()
     {
         $session = $this->getMinkSession();
-        $session->start();
-        $page = $this->setUpGenericCartTest($session);
-        $button = $page->find('css', '.cart-controls button[name=print]');
-        $this->assertTrue(is_object($button));
+        $page = $this->setUpGenericCartTest();
+        $button = $this->findCss($page, '.cart-controls button[name=print]');
 
         // First try clicking without selecting anything:
         $button->click();
@@ -434,8 +394,6 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
         $this->assertEquals(
             'print=true&id[]=VuFind|testsample1&id[]=VuFind|testsample2', $params
         );
-
-        $session->stop();
     }
 
     /**
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/FavoritesTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/FavoritesTest.php
index 98b242ef6da..dfaaa213ec5 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/FavoritesTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/FavoritesTest.php
@@ -63,19 +63,20 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
         }
     }
 
-    protected function gotoSearch($session)
+    protected function gotoSearch()
     {
+        $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Search/Home');
         $page = $session->getPage();
-        $page->find('css', '.searchForm [name="lookfor"]')->setValue('Dewey');
-        $page->find('css', '.btn.btn-primary')->click();
+        $this->findCss($page, '.searchForm [name="lookfor"]')->setValue('Dewey');
+        $this->findCss($page, '.btn.btn-primary')->click();
         return $page;
     }
 
-    protected function gotoRecord($session)
+    protected function gotoRecord()
     {
-        $page = $this->gotoSearch($session);
-        $page->find('css', '.result a.title')->click();
+        $page = $this->gotoSearch();
+        $this->findCss($page, '.result a.title')->click();
         return $page;
     }
 
@@ -92,48 +93,44 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
             ['config' => ['Site' => ['theme' => 'bootstrap3']]]
         );
 
-        $session = $this->getMinkSession();
-        $session->start();
-        $page = $this->gotoRecord($session);
+        $page = $this->gotoRecord();
 
-        $page->findById('save-record')->click();
-        $page->find('css', '.modal-body .createAccountLink')->click();
+        $this->findCss($page, '#save-record')->click();
+        $this->findCss($page, '.modal-body .createAccountLink')->click();
         // Empty
-        $this->assertNotNull(
-            $page->find('css', '.modal-body .btn.btn-primary.disabled')
-        );
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal-body .btn.btn-primary.disabled');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
 
         // Invalid email
         $this->fillInAccountForm($page, ['email' => 'blargasaurus']);
-        $this->assertNull(
-            $page->find('css', '.modal-body .btn.btn-primary.disabled')
-        );
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         // Correct
-        $page->findById('account_email')->setValue('username1@ignore.com');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->findById('save_list'));
+        $this->findCss($page, '#account_email')->setValue('username1@ignore.com');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '#save_list');
         // Make list
-        $page->findById('make-list')->click();
+        $this->findCss($page, '#make-list')->click();
         // Empty
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->findById('list_title'));
-        $page->findById('list_title')->setValue('Test List');
-        $page->findById('list_desc')->setValue('Just. THE BEST.');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertEquals($page->find('css', '#save_list option[selected]')->getHtml(), 'Test List');
-        $page->findById('add_mytags')->setValue('test1 test2 "test 3"');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.alert.alert-info')); // .success?
-        $page->find('css', '.modal-body .btn.btn-default')->click();
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '#list_title');
+        $this->findCss($page, '#list_title')->setValue('Test List');
+        $this->findCss($page, '#list_desc')->setValue('Just. THE BEST.');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->assertEquals($this->findCss($page, '#save_list option[selected]')->getHtml(), 'Test List');
+        $this->findCss($page, '#add_mytags')->setValue('test1 test2 "test 3"');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal .alert.alert-info'); // .success?
+        $this->findCss($page, '.modal-body .btn.btn-default')->click();
         // Check list page
+        $session = $this->getMinkSession();
         $recordURL = $this->stripHash($session->getCurrentUrl());
-        $page->find('css', '#savedLists a')->click();
-        $page->find('css', '.resultItemLine1 a')->click();
+        $this->snooze();
+        $this->findCss($page, '#savedLists a')->click();
+        $this->snooze();
+        $this->findCss($page, '.resultItemLine1 a')->click();
         $this->assertEquals($recordURL, $this->stripHash($session->getCurrentUrl()));
-        $page->find('css', '.logoutOptions a[title="Log Out"]')->click();
-        $session->stop();
+        $this->findCss($page, '.logoutOptions a[title="Log Out"]')->click();
     }
 
     public function testAddRecordToFavoritesLogin()
@@ -143,11 +140,9 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
             ['config' => ['Site' => ['theme' => 'bootstrap3']]]
         );
 
-        $session = $this->getMinkSession();
-        $session->start();
-        $page = $this->gotoRecord($session);
+        $page = $this->gotoRecord();
 
-        $page->findById('save-record')->click();
+        $this->findCss($page, '#save-record')->click();
         // Login
         // - empty
         $this->submitLoginForm($page);
@@ -163,24 +158,23 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
         $this->assertNull($page->find('css', '.modal-body #save_list'));
         // Make Two Lists
         // - One for the next test
-        $page->findById('make-list')->click();
-        $page->findById('list_title')->setValue('Future List');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '#make-list')->click();
+        $this->findCss($page, '#list_title')->setValue('Future List');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         $this->assertEquals(
-            $page->find('css', '#save_list option[selected]')->getHtml(),
+            $this->findCss($page, '#save_list option[selected]')->getHtml(),
             'Future List'
         );
         // - One for now
-        $page->findById('make-list')->click();
-        $page->findById('list_title')->setValue('Login Test List');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '#make-list')->click();
+        $this->findCss($page, '#list_title')->setValue('Login Test List');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         $this->assertEquals(
-            $page->find('css', '#save_list option[selected]')->getHtml(),
+            $this->findCss($page, '#save_list option[selected]')->getHtml(),
             'Login Test List'
         );
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.alert.alert-info')); // .success?
-        $session->stop();
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal .alert.alert-info'); // .success?
     }
 
     public function testAddRecordToFavoritesLoggedIn()
@@ -190,20 +184,19 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
             ['config' => ['Site' => ['theme' => 'bootstrap3']]]
         );
 
-        $session = $this->getMinkSession();
-        $session->start();
-        $page = $this->gotoRecord($session);
+        $page = $this->gotoRecord();
         // Login
-        $page->find('css', '#loginOptions a')->click();
+        $this->findCss($page, '#loginOptions a')->click();
         $this->fillInLoginForm($page, 'username1', 'test');
         $this->submitLoginForm($page);
-        $session->reload();
+        //$this->getMinkSession()->reload();
         // Save Record
-        $page->findById('save-record')->click();
-        $this->assertNotNull($page->find('css', '#save_list'));
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.alert.alert-info')); // .success?
-        $session->stop();
+        $this->snooze();
+        $this->findCss($page, '#save-record')->click();
+        $this->snooze();
+        $this->findCss($page, '#save_list');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal .alert.alert-info'); // .success?
     }
 
     public function testAddSearchItemToFavoritesNewAccount()
@@ -213,57 +206,54 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
             ['config' => ['Site' => ['theme' => 'bootstrap3']]]
         );
 
-        $session = $this->getMinkSession();
-        $session->start();
-        $page = $this->gotoSearch($session);
+        $page = $this->gotoSearch();
 
-        $page->find('css', '.save-record')->click();
-        $page->find('css', '.modal-body .createAccountLink')->click();
+        $this->findCss($page, '.save-record')->click();
+        $this->findCss($page, '.modal-body .createAccountLink')->click();
         // Empty
-        $this->assertNotNull(
-            $page->find('css', '.modal-body .btn.btn-primary.disabled')
-        );
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal-body .btn.btn-primary.disabled');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         $this->fillInAccountForm(
             $page, ['username' => 'username2', 'email' => 'blargasaurus']
         );
-        $this->assertNull(
-            $page->find('css', '.modal-body .btn.btn-primary.disabled')
-        );
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $page->findById('account_email')->setValue('username2@ignore.com');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '#account_email')->setValue('username2@ignore.com');
         // Test taken
-        $page->findById('account_username')->setValue('username1');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->findById('account_firstname'));
-        $page->findById('account_username')->setValue('username2');
+        $this->findCss($page, '#account_username')->setValue('username1');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '#account_firstname');
+        $this->findCss($page, '#account_username')->setValue('username2');
         // Correct
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->findById('save_list'));
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '#save_list');
         // Make list
-        $page->findById('make-list')->click();
+        $this->findCss($page, '#make-list')->click();
         // Empty
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->findById('list_title'));
-        $page->findById('list_title')->setValue('Test List');
-        $page->findById('list_desc')->setValue('Just. THE BEST.');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '#list_title');
+        $this->findCss($page, '#list_title')->setValue('Test List');
+        $this->findCss($page, '#list_desc')->setValue('Just. THE BEST.');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         $this->assertEquals(
-            $page->find('css', '#save_list option[selected]')->getHtml(),
+            $this->findCss($page, '#save_list option[selected]')->getHtml(),
             'Test List'
         );
-        $page->findById('add_mytags')->setValue('test1 test2 "test 3"');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.alert.alert-info')); // .success?
-        $page->find('css', '.modal-header .close')->click();
+        $this->findCss($page, '#add_mytags')->setValue('test1 test2 "test 3"');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.alert.alert-info'); // .success?
+        $this->findCss($page, '.modal-header .close')->click();
         // Check list page
-        $page->find('css', '.result a.title')->click();
+        $this->snooze();
+        $this->findCss($page, '.result a.title')->click();
+        $this->snooze();
+        $session = $this->getMinkSession();
         $recordURL = $session->getCurrentUrl();
-        $page->find('css', '.savedLists a')->click();
-        $page->find('css', '.resultItemLine1 a')->click();
-        $this->assertEquals($session->getCurrentUrl(), $recordURL);
-        $page->find('css', '.logoutOptions a[title="Log Out"]')->click();
-        $session->stop();
+        $this->findCss($page, '.savedLists a')->click();
+        $this->snooze();
+        $this->findCss($page, '.resultItemLine1 a')->click();
+        $this->snooze();
+        $this->assertEquals($recordURL, $session->getCurrentUrl());
+        $this->findCss($page, '.logoutOptions a[title="Log Out"]')->click();
     }
 
     public function testAddSearchItemToFavoritesLogin()
@@ -273,11 +263,9 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
             ['config' => ['Site' => ['theme' => 'bootstrap3']]]
         );
 
-        $session = $this->getMinkSession();
-        $session->start();
-        $page = $this->gotoSearch($session);
+        $page = $this->gotoSearch();
 
-        $page->find('css', '.save-record')->click();
+        $this->findCss($page, '.save-record')->click();
         // Login
         // - empty
         $this->submitLoginForm($page);
@@ -289,24 +277,24 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
         $this->assertNull($page->find('css', '.modal-body #save_list'));
         // Make Two Lists
         // - One for the next test
-        $page->findById('make-list')->click();
-        $page->findById('list_title')->setValue('Future List');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '#make-list')->click();
+        $this->findCss($page, '#list_title')->setValue('Future List');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         $this->assertEquals(
-            $page->find('css', '#save_list option[selected]')->getHtml(),
+            $this->findCss($page, '#save_list option[selected]')->getHtml(),
             'Future List'
         );
         // - One for now
-        $page->findById('make-list')->click();
-        $page->findById('list_title')->setValue('Login Test List');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '#make-list')->click();
+        $this->findCss($page, '#list_title')->setValue('Login Test List');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         $this->assertEquals(
-            $page->find('css', '#save_list option[selected]')->getHtml(),
+            $this->findCss($page, '#save_list option[selected]')->getHtml(),
             'Login Test List'
         );
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.alert.alert-info')); // .success?
-        $session->stop();
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->snooze();
+        $this->findCss($page, '.alert.alert-info'); // .success?
     }
 
     public function testAddSearchItemToFavoritesLoggedIn()
@@ -316,34 +304,21 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
             ['config' => ['Site' => ['theme' => 'bootstrap3']]]
         );
 
-        $session = $this->getMinkSession();
-        $session->start();
-        $page = $this->gotoSearch($session);
+        $page = $this->gotoSearch();
         // Login
-        $page->find('css', '#loginOptions a')->click();
+        $this->findCss($page, '#loginOptions a')->click();
         $this->fillInLoginForm($page, 'username2', 'test');
         $this->submitLoginForm($page);
-        $session->reload();
+        $this->snooze();    // wait for login
         // Save Record
-        $page->find('css', '.save-record')->click();
-        $this->assertNotNull($page->find('css', '#save_list'));
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.alert.alert-info')); // .success?
-        $session->stop();
-    }
-/*
-    public function testAddSearchToFavoritesNewAccount()
-    {
+        $this->findCss($page, '.save-record')->click();
+        $this->snooze();
+        $this->findCss($page, '#save_list');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->snooze();
+        $this->findCss($page, '.alert.alert-info'); // .success?
     }
 
-    public function testAddSearchToFavoritesLogin()
-    {
-    }
-
-    public function testAddSearchToFavoritesLoggedIn()
-    {
-    } */
-
     /**
      * Standard teardown method.
      *
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/RecordActionsTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/RecordActionsTest.php
index b087bfd030f..e6b57618fa4 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/RecordActionsTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/RecordActionsTest.php
@@ -66,13 +66,14 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
         }
     }
 
-    protected function gotoRecord($session)
+    protected function gotoRecord()
     {
+        $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Search/Home');
         $page = $session->getPage();
-        $page->find('css', '.searchForm [name="lookfor"]')->setValue('Dewey');
-        $page->find('css', '.btn.btn-primary')->click();
-        $page->find('css', '.result a.title')->click();
+        $this->findCss($page, '.searchForm [name="lookfor"]')->setValue('Dewey');
+        $this->findCss($page, '.btn.btn-primary')->click();
+        $this->findCss($page, '.result a.title')->click();
         return $page;
     }
 
@@ -88,46 +89,44 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
             ['config' => ['Site' => ['theme' => 'bootstrap3']]]
         );
 
-        $session = $this->getMinkSession();
-        $session->start();
         // Go to a record view
-        $page = $this->gotoRecord($session);
+        $page = $this->gotoRecord();
         // Click add comment without logging in
         // TODO Rewrite for comment and login coming
-        $page->findById('usercomments')->click();
-        $this->assertNotNull($page->find('css', '#comment'));
+        $this->findCss($page, '#usercomments')->click();
+        $this->findCss($page, '#comment');
         $this->assertEquals(
             'You must be logged in first',
-            $page->find('css', 'form.comment .btn.btn-primary')->getValue()
+            $this->findCss($page, 'form.comment .btn.btn-primary')->getValue()
         ); // Can Comment?
-        $page->find('css', 'form.comment .btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.modal.in')); // Lightbox open
-        $this->assertNotNull($page->find('css', '.modal [name="username"]'));
+        $this->findCss($page, 'form.comment .btn-primary')->click();
+        $this->findCss($page, '.modal.in'); // Lightbox open
+        $this->findCss($page, '.modal [name="username"]');
         // Create new account
-        $page->find('css', '.modal-body .createAccountLink')->click();
+        $this->findCss($page, '.modal-body .createAccountLink')->click();
         $this->fillInAccountForm($page);
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         // Make sure page updated for login
-        $page = $this->gotoRecord($session);
-        $page->findById('usercomments')->click();
+        $page = $this->gotoRecord();
+        $this->findCss($page, '#usercomments')->click();
         $this->assertEquals(
             'Add your comment',
-            $page->find('css', 'form.comment .btn.btn-primary')->getValue()
+            $this->findCss($page, 'form.comment .btn.btn-primary')->getValue()
         ); // Can Comment?
         $this->assertNull($page->find('css', '.comment.row'));
         // Add comment
-        $page->findById('comment')->setValue('one');
-        $page->find('css', 'form.comment .btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.comment.row'));
+        $this->findCss($page, '#comment')->setValue('one');
+        $this->findCss($page, 'form.comment .btn-primary')->click();
+        $this->findCss($page, '.comment.row');
         // "Add" empty comment
-        $page->find('css', 'form.comment .btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.comment.row'));
+        $this->findCss($page, 'form.comment .btn-primary')->click();
+        $this->findCss($page, '.comment.row');
         // Remove comment
-        $page->find('css', '.comment.row .delete')->click();
+        $this->findCss($page, '.comment.row .delete')->click();
+        $this->snooze(); // wait for UI update
         $this->assertNull($page->find('css', '.comment.row'));
         // Logout
-        $page->find('css', '.logoutOptions a[title="Log Out"]')->click();
-        $session->stop();
+        $this->findCss($page, '.logoutOptions a[title="Log Out"]')->click();
     }
 
     /**
@@ -142,37 +141,37 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
             ['config' => ['Site' => ['theme' => 'bootstrap3']]]
         );
 
-        $session = $this->getMinkSession();
-        $session->start();
         // Go to a record view
-        $page = $this->gotoRecord($session);
+        $page = $this->gotoRecord();
         // Click to add tag
-        $page->findByid('tagRecord')->click();
+        $this->findCss($page, '#tagRecord')->click();
         // Lightbox login open?
-        $this->assertNotNull($page->find('css', '.modal.in [name="username"]'));
+        $this->findCss($page, '.modal.in [name="username"]');
         // Make account
-        $page->find('css', '.modal-body .createAccountLink')->click();
+        $this->findCss($page, '.modal-body .createAccountLink')->click();
         $this->fillInAccountForm(
             $page, ['username' => 'username2', 'email' => 'test2@com.com']
         );
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.modal #addtag_tag'));
-        $page->find('css', '.modal .close')->click();
-        $page->find('css', '.logoutOptions a[title="Log Out"]')->click();
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal #addtag_tag');
+        $this->findCss($page, '.modal .close')->click();
+        $this->snooze(); // wait for display to update
+        $this->findCss($page, '.logoutOptions a[title="Log Out"]')->click();
         // Login
-        $page = $this->gotoRecord($session); // redirects to search home???
-        $page->findByid('tagRecord')->click();
+        $page = $this->gotoRecord(); // redirects to search home???
+        $this->findCss($page, '#tagRecord')->click();
         $this->fillInLoginForm($page, 'username2', 'test');
         $this->submitLoginForm($page);
-        $this->assertNotNull($page->find('css', '.modal #addtag_tag'));
+        //$this->findCss($page, '.modal #addtag_tag');
         // Add tags
-        $page->find('css', '.modal #addtag_tag')->setValue('one 2 "three 4" five');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $success = $page->find('css', '.modal-body .alert-info');
+        $this->findCss($page, '.modal #addtag_tag')->setValue('one 2 "three 4" five');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $success = $this->findCss($page, '.modal-body .alert-info');
         $this->assertTrue(is_object($success));
         $this->assertEquals('Tags Saved', $success->getText());
-        $page->find('css', '.modal .close')->click();
+        $this->findCss($page, '.modal .close')->click();
         // Count tags
+        $this->snooze(); // wait for UI update
         $tags = $page->findAll('css', '#tagList .tag');
         $this->assertEquals(4, count($tags));
         $tvals = [];
@@ -184,6 +183,8 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
         $this->assertEquals($tvals, ['2', 'five', 'one', 'three 4']);
         // Remove a tag
         $tags[0]->find('css', 'button')->click();
+        $this->snooze(); // wait for UI update
+        $tags = $page->findAll('css', '#tagList .tag');
         // Count tags with missing
         $sum = 0;
         foreach ($tags as $t) {
@@ -194,30 +195,35 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
         }
         $this->assertEquals(3, $sum);
         // Log out
-        $page->find('css', '.logoutOptions a[title="Log Out"]')->click();
+        $this->findCss($page, '.logoutOptions a[title="Log Out"]')->click();
+        $this->snooze(); // wait for UI update
+
         // Flat tags
         $this->assertNull($page->find('css', '#tagList .tag.selected'));
         $this->assertNull($page->find('css', '#tagList .tag .fa'));
         // Login with second account
-        $page->find('css', '#loginOptions a')->click();
-        $this->assertNotNull($page->find('css', '.modal.in [name="username"]'));
+        $this->findCss($page, '#loginOptions a')->click();
+        $this->snooze();
+        $this->findCss($page, '.modal.in [name="username"]');
         $this->fillInLoginForm($page, 'username1', 'test');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $page = $this->gotoRecord($session);
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->snooze();
+        $page = $this->gotoRecord();
         // Check selected == 0
         $this->assertNull($page->find('css', '#tagList .tag.selected'));
-        $this->assertNotNull($page->find('css', '#tagList .tag'));
-        $this->assertNotNull($page->find('css', '#tagList .tag .fa-plus'));
+        $this->findCss($page, '#tagList .tag');
+        $this->findCss($page, '#tagList .tag .fa-plus');
         // Click one
-        $page->find('css', '#tagList .tag button')->click();
+        $this->findCss($page, '#tagList .tag button')->click();
+        $this->snooze();
         // Check selected == 1
-        $this->assertNotNull($page->find('css', '#tagList .tag.selected'));
+        $this->findCss($page, '#tagList .tag.selected');
         // Click again
-        $page->find('css', '#tagList .tag button')->click();
+        $this->findCss($page, '#tagList .tag button')->click();
+        $this->snooze();
         // Check selected == 0
         $this->assertNull($page->find('css', '#tagList .tag.selected'));
-        $page->find('css', '.logoutOptions a[title="Log Out"]')->click();
-        $session->stop();
+        $this->findCss($page, '.logoutOptions a[title="Log Out"]')->click();
     }
 
     /**
@@ -232,47 +238,42 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
             ['config' => ['Site' => ['theme' => 'bootstrap3']]]
         );
 
-        // Go to the advanced search page
-        $session = $this->getMinkSession();
-        $session->start();
-
         // Go to a record view
-        $page = $this->gotoRecord($session);
+        $page = $this->gotoRecord();
         // Click email record without logging in
-        $page->findByid('mail-record')->click();
-        $this->assertNotNull($page->find('css', '.modal.in [name="username"]'));
+        $this->findCss($page, '#mail-record')->click();
+        $this->findCss($page, '.modal.in [name="username"]');
         // Login in Lightbox
         $this->fillInLoginForm($page, 'username1', 'test');
         $this->submitLoginForm($page);
         // Make sure Lightbox redirects to email view
-        $this->assertNotNull($page->find('css', '.modal #email_to'));
+        $this->findCss($page, '.modal #email_to');
         // Close lightbox
-        $page->find('css', '.modal .close')->click();
+        $this->findCss($page, '.modal .close')->click();
         // Click email
-        $page = $this->gotoRecord($session);
-        $page->findByid('mail-record')->click();
-        $this->assertNotNull($page->find('css', '.modal #email_to'));
+        $page = $this->gotoRecord();
+        $this->findCss($page, '#mail-record')->click();
+        $this->findCss($page, '.modal #email_to');
         // Type invalid email
-        $page->find('css', '.modal #email_to')->setValue('blargarsaurus');
-        $page->find('css', '.modal #email_from')->setValue('asdf@asdf.com');
-        $page->find('css', '.modal #email_message')->setValue('message');
+        $this->findCss($page, '.modal #email_to')->setValue('blargarsaurus');
+        $this->findCss($page, '.modal #email_from')->setValue('asdf@asdf.com');
+        $this->findCss($page, '.modal #email_message')->setValue('message');
         // Make sure form cannot submit
         /* TODO: Not working with validator
-        $session->executeScript('$(".modal form").validator();');
+        $this->getMinkSession()->executeScript('$(".modal form").validator();');
         $forms = $page->findAll('css', '.modal-body .form-group');
         foreach ($forms as $f) {
             var_dump($f->getHtml());
         }
-        $this->assertNotNull($page->find('css', '.modal .disabled'));
+        $this->findCss($page, '.modal .disabled');
         */
         // Send text to false email
-        $page->find('css', '.modal #email_to')->setValue('asdf@vufind.org');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal #email_to')->setValue('asdf@vufind.org');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         // Check for confirmation message
-        $this->assertNotNull($page->find('css', '.modal .alert-info'));
+        $this->findCss($page, '.modal .alert-info');
         // Logout
-        $page->find('css', '.logoutOptions a[title="Log Out"]')->click();
-        $session->stop();
+        $this->findCss($page, '.logoutOptions a[title="Log Out"]')->click();
     }
 
     /**
@@ -287,49 +288,42 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
             ['config' => ['Site' => ['theme' => 'bootstrap3']]]
         );
 
-        // Go to the advanced search page
-        $session = $this->getMinkSession();
-        $session->start();
-
         // Go to a record view
-        $page = $this->gotoRecord($session);
+        $page = $this->gotoRecord();
         // Click SMS
-        $page->findByid('sms-record')->click();
-        $this->assertNotNull($page->find('css', '.modal #sms_to'));
+        $this->findCss($page, '#sms-record')->click();
+        $this->findCss($page, '.modal #sms_to');
         // Type invalid phone numbers
         // - too empty
-        $page->find('css', '.modal #sms_to')->setValue('');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.modal .sms-error'));
+        $this->findCss($page, '.modal #sms_to')->setValue('');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal .sms-error');
         // - too short
-        $page->find('css', '.modal #sms_to')->setValue('123');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.modal .sms-error'));
+        $this->findCss($page, '.modal #sms_to')->setValue('123');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal .sms-error');
         // - too long
-        $page->find('css', '.modal #sms_to')->setValue('12345678912345678912345679');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.modal .sms-error'));
+        $this->findCss($page, '.modal #sms_to')->setValue('12345678912345678912345679');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal .sms-error');
         // - too lettery
-        $page->find('css', '.modal #sms_to')->setValue('123abc');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
-        $this->assertNotNull($page->find('css', '.modal .sms-error'));
+        $this->findCss($page, '.modal #sms_to')->setValue('123abc');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal .sms-error');
         // - just right
-        $page->find('css', '.modal #sms_to')->setValue('8005555555');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal #sms_to')->setValue('8005555555');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         $this->assertNull($page->find('css', '.modal .sms-error'));
         // - pretty just right
-        $page->find('css', '.modal #sms_to')->setValue('(800) 555-5555');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal #sms_to')->setValue('(800) 555-5555');
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         $this->assertNull($page->find('css', '.modal .sms-error'));
         // Send text to false number
-        $optionElement = $page->find('css', '.modal #sms_provider option');
+        $optionElement = $this->findCss($page, '.modal #sms_provider option');
         $page->selectFieldOption('sms_provider', 'verizon');
-        $page->find('css', '.modal-body .btn.btn-primary')->click();
+        $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         // Check for confirmation message
-        $this->assertNotNull($page->find('css', '.modal .alert-info'));
-        // Logout
-        $page->find('css', '.logoutOptions a[title="Log Out"]')->click();
-        $session->stop();
+        $this->findCss($page, '.modal .alert-info');
     }
 
     /**
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/RecordTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/RecordTest.php
index 0d9432da559..af0169e3e90 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/RecordTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/RecordTest.php
@@ -26,7 +26,6 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFindTest\Mink;
-use Behat\Mink\Session;
 
 /**
  * Mink test class for basic record functionality.
@@ -42,27 +41,26 @@ class RecordTest extends \VuFindTest\Unit\MinkTestCase
     /**
      * Test record tabs for a particular ID.
      *
-     * @param Session $session  Session
-     * @param string  $id       ID to load
-     * @param bool    $encodeId Should we URL encode the ID?
+     * @param string $id       ID to load
+     * @param bool   $encodeId Should we URL encode the ID?
      *
      * @return void
      */
-    protected function tryRecordTabsOnId(Session $session, $id, $encodeId = true)
+    protected function tryRecordTabsOnId($id, $encodeId = true)
     {
         $url = $this->getVuFindUrl(
             '/Record/' . ($encodeId ? rawurlencode($id) : $id)
         );
+        $session = $this->getMinkSession();
         $session->visit($url);
-        $this->assertEquals(200, $session->getStatusCode());
+        $this->assertHttpStatus(200);
         $page = $session->getPage();
-        $staffViewTab = $page->findById('details');
-        $this->assertTrue(is_object($staffViewTab));
+        $staffViewTab = $this->findCss($page, '#details');
         $this->assertEquals('Staff View', $staffViewTab->getText());
         $staffViewTab->click();
+        $this->snooze();
         $this->assertEquals($url . '#details', $session->getCurrentUrl());
-        $staffViewTable = $page->find('css', '#details-tab table.citation');
-        $this->assertTrue(is_object($staffViewTable));
+        $staffViewTable = $this->findCss($page, '#details-tab table.citation');
         $this->assertEquals('LEADER', substr($staffViewTable->getText(), 0, 6));
     }
 
@@ -73,10 +71,7 @@ class RecordTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testRecordTabsOnNormalId()
     {
-        $session = $this->getMinkSession();
-        $session->start();
-        $this->tryRecordTabsOnId($session, 'testsample1');
-        $session->stop();
+        $this->tryRecordTabsOnId('testsample1');
     }
 
     /**
@@ -86,10 +81,7 @@ class RecordTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testRecordTabsOnSpacedId()
     {
-        $session = $this->getMinkSession();
-        $session->start();
-        $this->tryRecordTabsOnId($session, 'dot.dash-underscore__3.space suffix');
-        $session->stop();
+        $this->tryRecordTabsOnId('dot.dash-underscore__3.space suffix');
     }
 
     /**
@@ -99,11 +91,8 @@ class RecordTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testRecordTabsOnPlusId()
     {
-        $session = $this->getMinkSession();
-        $session->start();
         // Skip encoding on this one, because Zend Framework doesn't URL encode
         // plus signs in route segments!
-        $this->tryRecordTabsOnId($session, 'theplus+andtheminus-', false);
-        $session->stop();
+        $this->tryRecordTabsOnId('theplus+andtheminus-', false);
     }
 }
-- 
GitLab