org.mousephenotype.www.SearchPageTest.java Source code

Java tutorial

Introduction

Here is the source code for org.mousephenotype.www.SearchPageTest.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 /**
 * Copyright  2014 EMBL - European Bioinformatics Institute
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.mousephenotype.www;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.junit.*;
import org.junit.runner.RunWith;
import org.mousephenotype.www.testing.model.PageStatus;
import org.mousephenotype.www.testing.model.SearchFacetTable;
import org.mousephenotype.www.testing.model.SearchImageTable.ImageFacetView;
import org.mousephenotype.www.testing.model.SearchPage;
import org.mousephenotype.www.testing.model.SearchPage.Facet;
import org.mousephenotype.www.testing.model.SearchPage.PageDirective;
import org.mousephenotype.www.testing.model.TestUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import uk.ac.ebi.generic.util.JSONRestUtil;
import uk.ac.ebi.phenotype.dao.PhenotypePipelineDAO;
import uk.ac.ebi.phenotype.service.GeneService;
import uk.ac.ebi.phenotype.util.Utils;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static org.junit.Assert.*;

/**
 *
 * @author ckchen@ebi.ac.uk (private methods)
 *
 * Generic configuration based on Mike's settings as below:
 *
 * These are selenium-based JUnit web tests that are configured (via the pom.xml) not to
 * run with the default profile because they take too long to complete. To run them,
 * use the 'web-tests' profile.
 *
 * These selenium tests use selenium's WebDriver protocol and thus need a hub
 * against which to run. The url for the hub is defined in the Test Packages
 * /src/test/resources/testConfig.properties file (driven by /src/test/resources/test-config.xml).
 *
 * To run these tests, edit /src/test/resources/testConfig.properties, making sure
 * that the properties 'seleniumUrl' and 'desiredCapabilities' are defined. Consult
 * /src/test/resources/test-config.xml for valid desiredCapabilities bean ids.
 *
 * Examples:
 * seleniumUrl=http://mi-selenium-win.windows.ebi.ac.uk:4444/wd/hub
 *      desiredCapabilities=firefoxDesiredCapabilities
 */

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:test-config.xml" })
public class SearchPageTest {

    @Autowired
    protected GeneService geneService;

    @Autowired
    protected String baseUrl;

    @Autowired
    protected WebDriver driver;

    @Autowired
    protected String seleniumUrl;

    @Autowired
    protected String solrUrl;

    @Autowired
    private PhenotypePipelineDAO phenotypePipelineDAO;

    private final String DATE_FORMAT = "yyyy/MM/dd HH:mm:ss";
    private final Logger logger = Logger.getLogger(this.getClass().getCanonicalName());

    // These constants define the default number of iterations for each that uses them. -1 means iterate over all.
    private final int MAX_MGI_LINK_CHECK_COUNT = 5; // -1 means test all links.
    private final int MAX_PHENOTYPE_TEST_PAGE_COUNT = 10; // -1 means test all pages.
    private final int TIMEOUT_IN_SECONDS = 120;
    private final int THREAD_WAIT_IN_MILLISECONDS = 1000;

    // These variables define the actual number of iterations for each test that uses them.
    // They use default values defined above but may be overridden on the command line using -Dxxx.
    private final int max_mgi_link_check_count = MAX_MGI_LINK_CHECK_COUNT;
    private final int max_phenotype_test_page_count = MAX_PHENOTYPE_TEST_PAGE_COUNT;
    private int timeout_in_seconds = TIMEOUT_IN_SECONDS;
    private int thread_wait_in_ms = THREAD_WAIT_IN_MILLISECONDS;

    private final StringBuffer verificationErrors = new StringBuffer();

    private final ArrayList<String> errLog = new ArrayList();

    private final HashMap<String, String> params = new HashMap();
    private final List<String> paramList = new ArrayList();
    private final List<String> cores = new ArrayList();
    private final List<String> errorList = new ArrayList();
    private final List<String> exceptionList = new ArrayList();
    private final List<String> successList = new ArrayList();
    private final static List<String> sumErrorList = new ArrayList();
    private final static List<String> sumSuccessList = new ArrayList();
    private static String startTime;
    private static int testCount;
    private WebDriverWait wait;

    @Before
    public void setup() {
        wait = new WebDriverWait(driver, timeout_in_seconds);
        if (Utils.tryParseInt(System.getProperty("TIMEOUT_IN_SECONDS")) != null)
            timeout_in_seconds = Utils.tryParseInt(System.getProperty("TIMEOUT_IN_SECONDS"));
        if (Utils.tryParseInt(System.getProperty("THREAD_WAIT_IN_MILLISECONDS")) != null)
            thread_wait_in_ms = Utils.tryParseInt(System.getProperty("THREAD_WAIT_IN_MILLISECONDS"));

        TestUtils.printTestEnvironment(driver, seleniumUrl);

        driver.navigate().refresh();
        driver.manage().timeouts().setScriptTimeout(timeout_in_seconds, TimeUnit.SECONDS);
        try {
            Thread.sleep(thread_wait_in_ms);
        } catch (Exception e) {
        }

        params.put("gene", "fq=*:*");
        params.put("mp", "fq=top_level_mp_term:*");
        params.put("disease", "fq=*:*");
        params.put("ma", "fq=selected_top_level_ma_term:*");
        params.put("impc_images", "fq=*:*");
        params.put("images", "fq=annotationTermId:M* OR expName:* OR symbol:*");

        String commonParam = "qf=auto_suggest&defType=edismax&wt=json&rows=0&q=*:*";
        final String geneParams = "/gene/select?" + commonParam + "&" + params.get("gene");
        final String mpParams = "/mp/select?" + commonParam + "&" + params.get("mp");
        final String diseaseParams = "/disease/select?" + commonParam + "&" + params.get("disease");
        final String maParams = "/ma/select?" + commonParam + "&" + params.get("ma");
        final String impc_imagesParams = "/impc_images/select?" + commonParam + "&" + params.get("impc_images");
        final String imagesParams = "/images/select?" + commonParam + "&" + params.get("images");

        paramList.add(geneParams);
        paramList.add(mpParams);
        paramList.add(diseaseParams);
        paramList.add(maParams);
        paramList.add(impc_imagesParams);
        paramList.add(imagesParams);

        cores.add("gene");
        cores.add("mp");
        cores.add("disease");
        cores.add("ma");
        cores.add("impc_images");
        cores.add("images");
    }

    @After
    public void teardown() {
        if (driver != null) {
            driver.quit();
        }
    }

    @BeforeClass
    public static void setUpClass() {
        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date date = new Date();
        startTime = dateFormat.format(date);
    }

    @AfterClass
    public static void tearDownClass() {
        System.out.println();
        System.out.println("SEARCH PAGE" + String.format("%8s", "started") + " at " + startTime);
        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date date = new Date();
        String endTime = dateFormat.format(date);

        System.out.println("SEARCH PAGE" + String.format("%8s", "ended") + " at " + endTime);

        if (sumErrorList.size() > 0) {
            System.out.println(sumErrorList.size() + " of " + testCount + " SEARCH PAGE TEST(s) FAILED");
            System.out.println(StringUtils.join(sumErrorList, "\n"));
        } else if (sumSuccessList.size() == testCount) {
            System.out.println("[SUCCESS] - ALL " + testCount + " SEARCH PAGE TESTS OK");
        } else {
            System.out.println("[FAILED] - SOME SEARCH PAGE TESTs NOT FINISHED");
        }
    }

    // TESTS

    @Test
    //@Ignore
    public void testAutosuggestForSpecificKnownGenes() throws Exception {
        testCount++;
        String testName = "testAutosuggestForSpecificKnownGenes";

        System.out.println("\n\n----- " + testName + " -----");
        Date start = new Date();

        successList.clear();
        errorList.clear();

        String[] geneSymbols = { "Klk4", "Del(7Gabrb3-Ube3a)1Yhj" };

        System.out.println(
                "TESTING autosuggest for specific gene symbols. NOTE: Results don't seem to be ordered, so it's possible the gene is beyond the first 10 shown.");
        String message;

        for (String geneSymbol : geneSymbols) {
            String target = baseUrl + "/search";

            SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO,
                    baseUrl);
            System.out.println("Testing symbol " + geneSymbol + ":\t. URL: " + driver.getCurrentUrl());

            List<SearchPage.AutosuggestRow> autoSuggestions = searchPage.getAutosuggest(geneSymbol);

            boolean found = false;
            for (SearchPage.AutosuggestRow row : autoSuggestions) {
                //                    log.info("annotationType: '" + row.annotationType + "'. value: '" + row.value + "'");
                if (row.value.equalsIgnoreCase(geneSymbol)) {
                    found = true;
                    break;
                }
            }
            if (found) {
                System.out.println("[PASSED]");
                successList.add(geneSymbol);
            } else {
                message = "[FAILED]: Expected to find gene id '" + geneSymbol
                        + "' in the autosuggest list but it was not found.";
                for (SearchPage.AutosuggestRow row : autoSuggestions) {
                    message += "\n" + row.toString();
                }
                System.out.println(message);
                errorList.add(message);
            }
        }

        TestUtils.printEpilogue(testName, start, errorList, null, successList, geneSymbols.length,
                geneSymbols.length);

        System.out.println();
    }

    @Test
    //@Ignore
    public void testAutosuggestMinCharacters() throws Exception {
        // test that there is a dropdown when at least 3 letters with match are entered into the input box
        testCount++;
        System.out.println();
        String testName = "testAutosuggestMinCharacters";

        System.out.println("\n\n----- " + testName + " -----");

        String queryStr = baseUrl + "/search";
        //System.out.println(queryStr);
        driver.get(queryStr);
        driver.navigate().refresh();
        String testKw = "mast";
        driver.findElement(By.cssSelector("input#s")).sendKeys(testKw);
        Thread.sleep(2000); // wait until the dropdown list pops up

        int numTerms = driver.findElements(By.cssSelector("ul.ui-autocomplete li")).size();
        if (numTerms > 0) {
            System.out.println("[PASSED] - " + testName);
            System.out.println("Test keyword " + testKw + " found " + numTerms + " suggested terms");
            sumSuccessList.add("passed");
        } else {
            String msg = "[FAILED] - " + testName + "\n" + "Test keyword: " + testKw + "\n";
            System.out.println(msg);
            sumErrorList.add(msg);
            fail("There was one error");
        }
    }

    @Test
    //@Ignore
    public void testTickingFacetFilters() throws Exception {
        testCount++;
        System.out.println();
        String testName = "testTickingFacetFilters";

        System.out.println("\n\n----- " + testName + " -----");
        System.out.println("TESTING clicking on a facet checkbox will add a filter to the filter summary box");
        System.out.println("TESTING removing a filter on the list will uncheck a corresponding checkbox");

        String message;
        successList.clear();
        errorList.clear();
        String target = baseUrl + "/search";
        logger.debug("target Page URL: " + target);
        SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO, baseUrl);

        // For each core:
        //   Click the first subfacet.
        //   Check that it is selected.
        //   Check that there is a filter matching the selected facet above the Genes facet.
        //   Click the first subfacet again to unselect it.
        //   Check that it is unselected.
        //   Check that there is no filter matching the just-unselected facet above the Genes facet.
        for (String core : cores) {
            String subfacetCheckboxCssSelector = "li#" + core + " li.fcat input[type='checkbox']";
            String subfacetTextCssSelector = "li#" + core + " li.fcat span.flabel";
            int iterationErrorCount = 0;
            Facet facet = searchPage.getFacetByCoreName(core);
            searchPage.openFacet(facet); // Open facet if it is not alreay opened.

            WebElement firstSubfacetElement = wait
                    .until(ExpectedConditions.elementToBeClickable(By.cssSelector(subfacetCheckboxCssSelector)));
            firstSubfacetElement.click(); // Select the first subfacet.

            searchPage.openFacet(facet); // Re-open the facet as, by design, it closed after the click() above.
            if (!firstSubfacetElement.isSelected()) { // Verify that the subfacet is selected.
                iterationErrorCount++;
                message = "Failed to check input filter for " + facet + " facet.";
                errorList.add(message);
                logger.error(message);
            }

            // Check that there is a filter matching the selected facet above the Genes facet.
            String facetText = driver.findElement(By.cssSelector(subfacetTextCssSelector)).getText();
            HashMap<Facet, SearchPage.FacetFilter> facetFilterHash = searchPage.getFacetFilter();
            List<String> facetFilterText = facetFilterHash.get(facet).subfacetTexts;
            boolean found = false;
            for (String facetFilter : facetFilterText) {
                if (facetFilter.contains(facetText)) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                iterationErrorCount++;
                message = "ERROR: Couldn't find subfacet '" + facetText + "' in facet " + facet;
                errorList.add(message);
                logger.error(message);
            }

            searchPage.openFacet(facet); // Open facet if it is not alreay opened.
            firstSubfacetElement.click(); // Deselect the first subfacet.

            searchPage.openFacet(facet); // Re-open the facet as, by design, it closed after the click() above.

            // The page becomes stale after the click() above, so we must re-fetch the WebElement objects.
            firstSubfacetElement = wait
                    .until(ExpectedConditions.elementToBeClickable(By.cssSelector(subfacetCheckboxCssSelector)));

            if (firstSubfacetElement.isSelected()) { // Verify that the subfacet is no longer selected.
                iterationErrorCount++;
                message = "Failed to uncheck input filter for " + facet + " facet.";
                errorList.add(message);
                logger.error(message);
            }

            // Check that there are no filters.
            if (searchPage.hasFilters()) {
                iterationErrorCount++;
                message = "ERROR: Expected filters to be cleared, but there were filters in place for facet "
                        + facet;
                errorList.add(message);
                logger.error(message);
            }

            if (iterationErrorCount == 0) {
                logger.info("   " + core + " OK");
                successList.add(core);
            }

            searchPage.clearFilters();
        }
        System.out.println();
        if (successList.size() == params.size()) {
            System.out.println("[PASSED] - " + testName);
            sumSuccessList.add("passed");
        } else {
            System.out.println("[FAILED] - " + testName + "\n" + StringUtils.join(errorList, "\n"));
            sumErrorList.add("[FAILED] - " + testName + "\n" + StringUtils.join(errorList, "\n"));
            fail("There were " + sumErrorList.size() + " errors.");
        }
        System.out.println();
    }

    // Verify that random genes appear in the autosuggest list.
    @Test
    //@Ignore
    public void testQueryingRandomGeneSymbols() throws Exception {
        testCount++;
        String testName = "testQueryingRandomGeneSymbols";

        System.out.println("\n\n----- " + testName + " -----");
        Date start = new Date();

        successList.clear();
        errorList.clear();

        Random rn = new Random();
        int startIndex = rn.nextInt(60000 - 0 + 1) + 1;
        int nbRows = 20;
        System.out.println("TESTING " + nbRows + " random gene symbols");

        String target = baseUrl + "/search#fq=*:*&facet=gene";
        logger.info("URL: " + target);
        String queryString = solrUrl + "/gene/select?q=*:*&start=" + startIndex + "&rows=" + nbRows
                + "&fl=marker_symbol&wt=json&indent=true";

        JSONObject geneResults = JSONRestUtil.getResults(queryString);
        JSONArray docs = JSONRestUtil.getDocArray(geneResults);
        String message;

        if (docs != null) {
            int size = docs.size();
            for (int i = 0; i < size; i++) {
                String geneSymbol1 = docs.getJSONObject(i).getString("marker_symbol");

                SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO,
                        baseUrl);
                searchPage.submitSearch(geneSymbol1);
                TestUtils.sleep(5000); // Sleep for a bit to allow autocomplete to catch up.

                List<WebElement> elems = driver
                        .findElements(By.cssSelector("ul#ui-id-1 li.ui-menu-item a span b.sugTerm"));
                String geneSymbol2 = null;
                for (WebElement elem : elems) {
                    String autosuggestGene = elem.getText();
                    if (autosuggestGene.equals(geneSymbol1)) {
                        geneSymbol2 = elem.getText();
                        break;
                    }
                }

                if (geneSymbol1.equals(geneSymbol2)) {
                    logger.info("[" + i + "] (OK): '" + geneSymbol1 + "'");
                    successList.add(geneSymbol1);
                } else {
                    message = "[" + i + "] (FAIL): Expected to find gene id '" + geneSymbol1
                            + "' in the autosuggest list but it was not found.";
                    logger.info(message);
                    errorList.add(message);
                }
            }
        }
        System.out.println();
        if (successList.size() == nbRows) {
            System.out.println("[PASSED] - " + testName);
            sumSuccessList.add("passed");
        } else {
            System.out.println("[FAILED] - " + testName + "\n" + StringUtils.join(errorList, "\n"));
            sumErrorList.add("[FAILED] - " + testName + "\n" + StringUtils.join(errorList, "\n"));
            TestUtils.printEpilogue(testName, start, errorList, null, successList, nbRows, 1);
            fail("There were " + sumErrorList.size() + " errors.");

        }
        System.out.println();
    }

    @Test
    //@Ignore
    public void testRandomMgiIds() throws Exception {
        testCount++;
        System.out.println();
        String testName = "testRandomMgiIds";

        System.out.println("\n\n----- " + testName + " -----");

        successList.clear();
        errorList.clear();

        String newQueryString = "/gene/select?q=mgi_accession_id:*&fq=-marker_symbol:CGI_* AND -marker_symbol:Gm*&fl=mgi_accession_id,marker_symbol&wt=json";
        Random rn = new Random();
        int startIndex = rn.nextInt(40000 - 0 + 1) + 1;
        int nbRows = 20;
        newQueryString += "&start=" + startIndex + "&rows=" + nbRows;
        //System.out.println("newQueryString=" + newQueryString);
        System.out.println("TESTING " + nbRows + " random MGI IDs");

        JSONObject geneResults = JSONRestUtil.getResults(solrUrl + newQueryString);
        JSONArray docs = JSONRestUtil.getDocArray(geneResults);

        if (docs != null) {
            int size = docs.size();
            int count;
            for (int i = 0; i < size; i++) {

                count = i + 1;
                String mgiId = docs.getJSONObject(i).getString("mgi_accession_id");
                String symbol = docs.getJSONObject(i).getString("marker_symbol");
                System.out.print("Testing MGI ID " + String.format("%3d", count) + ": "
                        + String.format("%-10s", mgiId) + "\t=>\t");

                driver.get(baseUrl + "/search?q=" + mgiId);
                driver.navigate().refresh();

                //new WebDriverWait(driver, 25).until(ExpectedConditions.visibilityOfElementLocated(By.id("div.geneCol")));
                new WebDriverWait(driver, 25)
                        .until(ExpectedConditions.elementToBeClickable(By.cssSelector("div.geneCol")));
                //WebElement geneLink = driver.findElement(By.xpath("//a[@href='/data/genes/" + mgiId + "'"));
                WebElement geneLink = null;
                try {
                    geneLink = driver.findElement(By.cssSelector("div.geneCol a").linkText(symbol));
                    System.out.println("OK");
                    successList.add(mgiId);
                    //Thread.sleep(thread_wait_in_seconds);
                } catch (Exception e) {
                    System.out.println("FAILED");
                    errorList.add(mgiId);
                    continue;
                }
                try {
                    Thread.sleep(thread_wait_in_ms);
                } catch (Exception e) {
                }
            }
            System.out.println();
            if (successList.size() == nbRows) {
                System.out.println("[PASSED] - " + testName);
                sumSuccessList.add("passed");
            } else {
                System.out.println("[FAILED] - " + testName + "\n" + StringUtils.join(errorList, "\n"));
                sumErrorList.add("[FAILED] - " + testName + "\n" + StringUtils.join(errorList, "\n"));
                fail("There were " + sumErrorList.size() + " errors.");
            }
            System.out.println();
        }
    }

    @Test
    //@Ignore
    public void testPhrase() throws Exception {
        specialStrQueryTest("testPhrase", "grip strength");
    }

    @Test
    //@Ignore
    public void testPhraseInQuotes() throws Exception {
        specialStrQueryTest("testPhraseInQuotes", "\"zinc finger protein\"");
    }

    @Test
    //@Ignore
    public void testLeadingWildcard() throws Exception {
        specialStrQueryTest("testLeadingWildcard", "*rik");
    }

    @Test
    //@Ignore
    public void testTrailingWildcard() throws Exception {
        specialStrQueryTest("testTrailingWildcard", "hox*");
    }

    @Test
    //@Ignore
    public void testTwist1() throws Exception {
        String testName = "testTwist1";
        String searchString = "twist1";

        downloadTestEngine(testName, searchString);
    }

    @Test
    //@Ignore
    public void testPagination() throws Exception {
        testCount++;
        System.out.println();
        String testName = "testPagination";

        System.out.println("\n\n----- " + testName + " -----");
        String target;
        String message;
        final String showing_1 = "Showing 1 to ";
        final String showing_11 = "Showing 11 to ";
        Date start = new Date();
        String expectedShowingPhrase = "";
        String actualShowing = "";

        successList.clear();
        errorList.clear();
        exceptionList.clear();

        for (String core : cores) {
            target = baseUrl + "/search#" + params.get(core) + "&facet=" + core;
            System.out.println("Testing URL: " + target);
            try {
                SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO,
                        baseUrl);
                searchPage.clickFacetById(core);

                // Upon entry, the 'showing' string should start with 'Showing 1 to 10 of".
                expectedShowingPhrase = showing_1;
                actualShowing = searchPage.getShowing().toString();
                if (!actualShowing.contains(expectedShowingPhrase)) {
                    message = "ERROR: Expected '" + expectedShowingPhrase + "' but found '" + actualShowing + "'.";
                    System.out.println(message);
                    errorList.add(message);
                }

                if (searchPage.getNumPageButtons() > 3) { // Previous, page, Next
                    // Wait for facet page to load, then click the page '2' link. The 'showing' string should start with 'Showing 11 to 20 of".
                    searchPage.clickPageButton(PageDirective.SECOND_NUMBERED);
                    expectedShowingPhrase = showing_11;
                    actualShowing = searchPage.getShowing().toString();
                    if (!actualShowing.contains(expectedShowingPhrase)) {
                        message = "ERROR: Expected '" + expectedShowingPhrase + "' but found '" + actualShowing
                                + "'.";
                        System.out.println(message);
                        errorList.add(message);
                    }
                }

                if (errorList.isEmpty())
                    successList.add("Success!");
            } catch (Exception e) {
                message = "EXCEPTION: Expected '" + expectedShowingPhrase + "' but found '" + actualShowing
                        + "'. message: " + e.getLocalizedMessage();
                System.out.println(message);
                exceptionList.add(message);
                e.printStackTrace();
            }
        }

        if ((errorList.isEmpty()) && (exceptionList.isEmpty())) {
            System.out.println("[PASSED] - " + testName);
            sumSuccessList.add("passed");
        }

        TestUtils.printEpilogue(testName, start, errorList, exceptionList, successList, cores.size(), cores.size());
    }

    @Test
    //@Ignore
    public void testFacetCountsNoSearchTerm() throws Exception {
        testCount++;
        System.out.println();
        String testName = "testFacetCountsNoSearchTerm";

        System.out.println("\n\n----- " + testName + " -----");
        Date start = new Date();

        successList.clear();
        errorList.clear();
        Map solrCoreCountMap = getSolrCoreCounts(null);
        int recordCount = 0;

        for (String core : cores) {
            recordCount++;
            String target = baseUrl + "/search#" + params.get(core) + "&facet=" + core;
            PageStatus status = facetCountEngine(target);
            if (status.hasErrors()) {
                errorList.add("[FAILED] - " + testName + "\n" + status.toStringErrorMessages());
            } else {
                successList.add("passed");
            }

            // Compare solr core count to page result count.

            // 26-Mar-2015 (mrelac) Skip the gene core count compare. The rules are fuzzy.
            if (core.equals(SearchPage.GENE_CORE))
                continue;

            recordCount++;
            SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO,
                    baseUrl);
            int facetCountFromSolr = (int) solrCoreCountMap.get(core);
            int resultCount = searchPage.getResultCount();

            if (facetCountFromSolr != resultCount) {
                errorList.add("[FAILED] - " + testName + "\n" + "facetCountFromSolr (" + facetCountFromSolr
                        + ") is not equal to page results count (" + resultCount + ").");
            } else {
                successList.add("passed");
            }
        }

        if ((errorList.isEmpty()) && (exceptionList.isEmpty())) {
            System.out.println("[PASSED] - " + testName);
            sumSuccessList.add("passed");
        }

        TestUtils.printEpilogue(testName, start, errorList, null, successList, recordCount, recordCount);
    }

    private class SearchTermGroup {
        private final String pageTarget;
        private final String solrTarget;

        public SearchTermGroup(String pageTarget, String solrTarget) {
            this.pageTarget = pageTarget;
            this.solrTarget = solrTarget;
        }
    }

    // Here's a good site to use for decoding: http://meyerweb.com/eric/tools/dencoder/
    SearchTermGroup[] staticSearchTermGroups = { new SearchTermGroup("leprot", "leprot") // leprot
            , new SearchTermGroup("!", "!") // !    %21
            , new SearchTermGroup("@", "@") // @    %40
            , new SearchTermGroup("", "\\%E2%82%AC") //     %E2%82%AC
            , new SearchTermGroup("", "\\%C2%A3") //     %C2%A3
            , new SearchTermGroup("\\%23", "\\%23") // #    %23
            , new SearchTermGroup("$", "$") // $    %24
            , new SearchTermGroup("\\%25", "\\%25") // %    %25
            , new SearchTermGroup("^", "^") // ^    %5E
            , new SearchTermGroup("\\%26", "\\%26") // &    %26
            , new SearchTermGroup("\\*", "\\%2A") // *    %2A
            , new SearchTermGroup("(", "(") // (    %28
            , new SearchTermGroup(")", ")") // )    %29
            , new SearchTermGroup("-", "-") // -    %2D (hyphen)
            , new SearchTermGroup("_", "_") // _    %5F (underscore)
            , new SearchTermGroup("\\=", "\\=") // =    %3D
            , new SearchTermGroup("\\%2B", "\\%2B") // +    %2B
            , new SearchTermGroup("\\[", "\\[") // [    %5B
            , new SearchTermGroup("\\]", "\\]") // [    %5D
            , new SearchTermGroup("{", "\\%7B") // {    %7B
            , new SearchTermGroup("}", "\\%7D") // }    %7D
            , new SearchTermGroup("\\:", "\\:") // :    %3A
            , new SearchTermGroup(";", ";") // ;    %3B
            , new SearchTermGroup("'", "'") // '    %27 (single quote)
            , new SearchTermGroup("\\\"", "\\\"") // "    %22 (double quote)
            , new SearchTermGroup("|", "|") // |    %7C
            , new SearchTermGroup(",", ",") // ,    %2C (comma)
            , new SearchTermGroup(".", ".") // .    %2E (period)
            , new SearchTermGroup("<", "<") // <    %3C
            , new SearchTermGroup(">", ">") // >    %3E
            , new SearchTermGroup("\\%2F", "\\%2F") // /    %2F
            , new SearchTermGroup("\\?", "\\?") // ?    %3F
            , new SearchTermGroup("`", "`") // `    %60 (backtick)
            , new SearchTermGroup("\\~", "\\~") // ~    %7E
            , new SearchTermGroup("", "\\%C3%A9") //     %C3%A9
            , new SearchTermGroup("", "\\%C3%A5") //     %C3%A5
            , new SearchTermGroup("", "\\%C3%A7") //     %C3%A7
            , new SearchTermGroup("", "\\%C3%9F") //     %C3%9F
            , new SearchTermGroup("?", "\\%C4%8D") // ?    %C4%8D
            , new SearchTermGroup("", "\\%C3%BC") //     %C3%BC
            , new SearchTermGroup("", "\\%C3%B6") //     %C3%B6
    };

    @Test
    //@Ignore
    public void testFacetCountsSpecialCharacters() throws Exception {
        testCount++;
        System.out.println();
        String testName = "testFacetCountsSpecialCharacters";

        System.out.println("\n\n----- " + testName + " -----");
        Date start = new Date();

        successList.clear();
        errorList.clear();

        // Create an array of SearchTermGroup from searchTermGroups that expands the original list by 4,
        // prepending '*', appending '*', and prepending AND appending '*' to the original searchTermGroups values.
        // Example:  "leprot", "leprot" becomes:
        //      "leprot",   "leprot"
        //      "*leprot",  "*leprot"
        //      "leprot*",  "leprot*"
        //      "*leprot*", "*leprot*"
        List<SearchTermGroup> searchTermGroupListWildcard = new ArrayList();
        for (SearchTermGroup staticSearchTermGroup : staticSearchTermGroups) {
            searchTermGroupListWildcard
                    .add(new SearchTermGroup(staticSearchTermGroup.pageTarget, staticSearchTermGroup.solrTarget));
            searchTermGroupListWildcard.add(new SearchTermGroup("*" + staticSearchTermGroup.pageTarget,
                    "*" + staticSearchTermGroup.solrTarget));
            searchTermGroupListWildcard.add(new SearchTermGroup(staticSearchTermGroup.pageTarget + "*",
                    staticSearchTermGroup.solrTarget + "*"));
            searchTermGroupListWildcard.add(new SearchTermGroup("*" + staticSearchTermGroup.pageTarget + "*",
                    "*" + staticSearchTermGroup.solrTarget + "*"));
        }
        SearchTermGroup[] searchTermGroupWildcard = searchTermGroupListWildcard.toArray(new SearchTermGroup[0]);

        PageStatus status = new PageStatus();
        for (SearchTermGroup searchTermGroup : searchTermGroupWildcard) {
            // logging/debugging statements:
            //            Map solrCoreCountMap = getSolrCoreCounts(searchTermGroup);
            //            Set<Map.Entry<String, Integer>> entrySet = solrCoreCountMap.entrySet();
            //            for (Map.Entry<String, Integer> entry : entrySet) {
            //                log.info("Core: " + entry.getKey() + ". Count: " + entry.getValue());
            //            }

            // Build the solarUrlCounts.
            String target = baseUrl + "/search?q=" + searchTermGroup.pageTarget;

            status.add(facetCountEngine(target, searchTermGroup));
        }

        if (status.hasErrors()) {
            sumErrorList.add("[FAILED] - " + testName + "\n" + status.toStringErrorMessages());
            TestUtils.printEpilogue(testName, start, status.getErrorMessages(), null, successList, paramList.size(),
                    paramList.size());
        } else if (status.hasWarnings()) {
            sumErrorList.add("[WARNINGS] - " + testName + "\n" + status.toStringWarningMessages());
            TestUtils.printEpilogue(testName, start, status.getWarningMessages(), null, successList,
                    paramList.size(), paramList.size());
        } else {
            System.out.println("[PASSED] - " + testName + ".");
            sumSuccessList.add("passed");
        }

        System.out.println();

    }

    /**
     * Test for Jira bug MPII-806: from the search page, searching for the characters
     * "fasting glu" should autosuggest 'fasting glucose'. Click on 'fasting glucose'
     * and verify that the correct phenotype page appears.
     * @throws Exception 
     */
    @Test
    //@Ignore
    public void testMPII_806() throws Exception {
        Date start = new Date();
        successList.clear();
        errorList.clear();
        testCount++;
        System.out.println();
        String testName = "testMPII_806";

        System.out.println("\n\n----- " + testName + " -----");

        String queryStr = baseUrl + "/search";
        driver.get(queryStr);
        driver.navigate().refresh();
        String characters = "fasting glu";
        driver.findElement(By.cssSelector("input#s")).sendKeys(characters);

        // Wait for dropdown list to appear with 'blood glucose'.
        String xpathSelector = "//ul[@id='ui-id-1']/li[@class='ui-menu-item']/a";
        WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpathSelector)));
        if (!element.getText().contains("fasting glucose")) {
            errorList.add("ERROR: Expected 'fasting glucose' but found '" + element.getText() + "'");
        } else {
            element.click();
            element = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//div[@id='resultMsg']")));
            if (element.getText().contains("Found") == false) {
                errorList.add("ERROR: Expected 'Found xxx genes' message. Text = '" + element.getText() + "'");
            }
        }

        if ((errorList.isEmpty() && (exceptionList.isEmpty())))
            successList.add((testName + ": OK"));

        TestUtils.printEpilogue(testName, start, errorList, exceptionList, successList, 1, 1);
    }

    /**
     * Test for Jira bug MPII-1175: from the search page, searching for the characters
     * "fasting glu" should autosuggest 'fasting glucose'. Click on 'fasting glucose'
     * and verify that the correct phenotype page appears.
     * @throws Exception 
     */
    @Test
    //@Ignore
    public void testMPII_1175() throws Exception {
        String testName = "testMPII_1175";
        String searchString = null;
        Date start = new Date();
        PageStatus status = new PageStatus();

        if (searchString == null)
            searchString = "";

        System.out.println("\n\n----- " + testName + " -----");

        try {
            // Apply searchPhrase. Click on this facet. Click on a random page. Click on each download type: Compare page values with download stream values.
            String target = baseUrl + "/search";
            // target = "https://dev.mousephenotype.org/data/search?q=ranbp2#fq=*:*&facet=gene";
            SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO,
                    baseUrl);
            if (!searchString.isEmpty()) {
                searchPage.submitSearch(searchString + "\n");
            }

            SearchPage.Facet[] facets = { SearchPage.Facet.ANATOMY, SearchPage.Facet.DISEASES,
                    SearchPage.Facet.GENES, SearchPage.Facet.IMAGES, SearchPage.Facet.IMPC_IMAGES,
                    SearchPage.Facet.PHENOTYPES };

            for (SearchPage.Facet facet : facets) {
                searchPage.clickFacet(facet);
                searchPage.clickPageButton();
                // http://ves-ebi-d0:8080/mi/impc/dev/phenotype-archive/search#fq=top_level_mp_term:*&facet=mp
                //searchPage.clickPageButton(SearchPage.PageDirective.THIRD_NUMBERED);
                //TestUtils.sleep(5000);

                //http://ves-ebi-d0:8080/mi/impc/dev/phenotype-archive/search#fq=*:*&facet=mp
                //searchPage.clickPageButton(SearchPage.PageDirective.SECOND_NUMBERED);
                //TestUtils.sleep(5000);

                searchPage.setNumEntries(SearchFacetTable.EntriesSelect._10);
                System.out.println("Testing " + facet + " facet. Search string: '" + searchString + "'. URL: "
                        + driver.getCurrentUrl());
                status.add(searchPage.validateDownload(facet));
            }
        } catch (Exception e) {
            String message = "EXCEPTION: SearchPageTest." + testName + "(): Message: " + e.getLocalizedMessage();
            System.out.println(message);
            e.printStackTrace();
            status.addError(message);
        } finally {
            if (status.hasErrors()) {
                errorList.add(status.toStringErrorMessages());
            } else {
                successList.add(testName + ": SUCCESS.");
            }

            TestUtils.printEpilogue(testName, start, errorList, exceptionList, successList, 1, 1);
        }

    }

    @Test
    //@Ignore
    public void testDefaultDownload() throws Exception {
        String testName = "testDefaultDownload";
        String searchString = null;

        downloadTestEngine(testName, searchString);
    }

    @Test
    //@Ignore
    public void testBoneDownload() throws Exception {
        String testName = "testBoneDownload";
        String searchString = "bone";

        downloadTestEngine(testName, searchString);
    }

    @Test
    //@Ignore
    public void testBrachydactyly() throws Exception {
        String testName = "testBrachydactyly";
        String searchString = "brachydactyly";

        downloadTestEngine(testName, searchString);
    }

    @Test
    //@Ignore
    public void testLegDownload() throws Exception {
        String testName = "testLegDownload";
        String searchString = "leg";

        downloadTestEngine(testName, searchString);
    }

    // This test doesn't use the download test engine as it requires an extra
    // click to switch to the Image facet's 'Image' view.
    @Test
    //@Ignore
    public void testImageFacetImageView() throws Exception {
        String testName = "testImageFacetImageView";
        String searchString = "";
        Date start = new Date();
        PageStatus status = new PageStatus();
        Facet facet;

        System.out.println("\n\n----- " + testName + " -----");

        try {
            String target = baseUrl + "/search";
            // target = "https://dev.mousephenotype.org/data/search?q=ranbp2#fq=*:*&facet=gene";
            SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO,
                    baseUrl);

            facet = Facet.IMAGES;
            searchPage.clickFacet(facet);
            searchPage.getImageTable().setCurrentView(ImageFacetView.IMAGE_VIEW);
            //            searchPage.clickPageButton();
            //searchPage.clickPageButton(SearchPage.PageDirective.LAST);
            //TestUtils.sleep(2000);
            System.out.println("Testing " + facet + " facet. Search string: '" + searchString + "'. URL: "
                    + driver.getCurrentUrl());
            status.add(searchPage.validateDownload(facet));

        } catch (Exception e) {
            String message = "EXCEPTION: SearchPageTest." + testName + "(): Message: " + e.getLocalizedMessage();
            System.out.println(message);
            e.printStackTrace();
            status.addError(message);
        } finally {
            if (status.hasErrors()) {
                errorList.add(status.toStringErrorMessages());
            } else {
                successList.add(testName + ": SUCCESS.");
            }

            TestUtils.printEpilogue(testName, start, errorList, exceptionList, successList, 1, 1);
        }
    }

    // This test doesn't use the download test engine as it requires an extra
    // click to switch to the Image facet's 'Image' view.
    @Test
    //@Ignore
    public void testImpcImageFacetImageView() throws Exception {
        String testName = "testImpcImageFacetImageView";
        String searchString = "";
        Date start = new Date();
        PageStatus status = new PageStatus();
        Facet facet;

        System.out.println("\n\n----- " + testName + " -----");

        try {
            String target = baseUrl + "/search";
            // target = "https://dev.mousephenotype.org/data/search?q=ranbp2#fq=*:*&facet=gene";
            SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO,
                    baseUrl);

            facet = Facet.IMPC_IMAGES;
            searchPage.clickFacet(facet);
            searchPage.getImpcImageTable().setCurrentView(ImageFacetView.IMAGE_VIEW);

            System.out.println("Testing " + facet + " facet. Search string: '" + searchString + "'. URL: "
                    + driver.getCurrentUrl());
            status.add(searchPage.validateDownload(facet));

        } catch (Exception e) {
            String message = "EXCEPTION: SearchPageTest." + testName + "(): Message: " + e.getLocalizedMessage();
            System.out.println(message);
            e.printStackTrace();
            status.addError(message);
        } finally {
            if (status.hasErrors()) {
                errorList.add(status.toStringErrorMessages());
            } else {
                successList.add(testName + ": SUCCESS.");
            }

            TestUtils.printEpilogue(testName, start, errorList, exceptionList, successList, 1, 1);
        }
    }

    // This test was spawned from testImageFacetImageView() when it came across
    // a 500 response from the server when the last page was selected.
    @Test
    //@Ignore
    public void testImageFacetImageViewLastPage() throws Exception {
        String testName = "testImageFacetImageViewLastPage";
        String searchString = "";
        Date start = new Date();
        PageStatus status = new PageStatus();

        System.out.println("\n\n----- " + testName + " -----");

        try {
            String target = baseUrl + "/search";
            // target = "https://dev.mousephenotype.org/data/search?q=ranbp2#fq=*:*&facet=gene";
            SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO,
                    baseUrl);
            Facet facet = Facet.IMAGES;
            searchPage.clickFacet(facet);
            searchPage.getImageTable().setCurrentView(ImageFacetView.IMAGE_VIEW);
            searchPage.clickPageButton(SearchPage.PageDirective.LAST);
            TestUtils.sleep(2000);
            System.out.println("Testing " + facet + " facet. Search string: '" + searchString + "'. URL: "
                    + driver.getCurrentUrl());
            status.add(searchPage.validateDownload(facet));
        } catch (Exception e) {
            String message = "EXCEPTION: SearchPageTest." + testName + "(): Message: " + e.getLocalizedMessage();
            System.out.println(message);
            e.printStackTrace();
            status.addError(message);
        } finally {
            if (status.hasErrors()) {
                errorList.add(status.toStringErrorMessages());
            } else {
                successList.add(testName + ": SUCCESS.");
            }

            TestUtils.printEpilogue(testName, start, errorList, exceptionList, successList, 1, 1);
        }
    }

    // Test that when Wnt1 is selected, it is at the top of the autosuggest list.
    @Test
    //@Ignore
    public void testWnt1IsAtTop() throws Exception {
        String testName = "testWnt1IsAtTop";
        String searchString = "Wnt1";
        String target = baseUrl + "/search";

        System.out.println("\n\n----- " + testName + " -----");

        SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO, baseUrl);
        System.out.println(
                "\nTesting Gene facet. Search string: '" + searchString + "'. URL: " + driver.getCurrentUrl());
        List<SearchPage.AutosuggestRow> rows = searchPage.getAutosuggest(searchString);
        String expectedResult = "wnt1";
        String actualResult = rows.get(0).value.toLowerCase();
        assertEquals(expectedResult, actualResult);
    }

    // Test that when Wnt1 is selected, it is at the top of the autosuggest list.
    @Test
    //@Ignore
    public void testHox() throws Exception {
        String testName = "testHox";
        String searchString = "Hox";
        String target = baseUrl + "/search";

        System.out.println("\n\n----- " + testName + " -----");

        SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO, baseUrl);
        System.out.println(
                "\nTesting Gene facet. Search string: '" + searchString + "'. URL: " + driver.getCurrentUrl());
        List<SearchPage.AutosuggestRow> rows = searchPage.getAutosuggest(searchString);
        String expectedStartsWith = "Hox";
        for (int i = 0; i < rows.size(); i++) {
            SearchPage.AutosuggestRow row = rows.get(i);
            String errMsg = "Row[" + i + "]: Expected autosuggest row to begin with 'Hox'. Row value = "
                    + row.value;
            assertTrue(errMsg, row.value.startsWith(expectedStartsWith));
        }
    }

    // Test that when Wnt1 is selected, it is at the top of the autosuggest list.
    @Test
    //@Ignore
    public void testHoxStar() throws Exception {
        String testName = "testHoxStar";
        String searchString = "Hox*";
        String target = baseUrl + "/search";

        System.out.println("\n\n----- " + testName + " -----");

        SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO, baseUrl);
        System.out.println(
                "\nTesting Gene facet. Search string: '" + searchString + "'. URL: " + driver.getCurrentUrl());
        List<SearchPage.AutosuggestRow> rows = searchPage.getAutosuggest(searchString);
        String expectedStartsWith = "Hox";
        assertTrue("Expected 10 autosuggest rows. Found " + rows.size() + " rows.", rows.size() == 10);
        for (int i = 0; i < rows.size(); i++) {
            SearchPage.AutosuggestRow row = rows.get(i);
            String errMsg = "Row[" + i + "]: Expected autosuggest row to begin with 'Hox'. Row value = "
                    + row.value;
            assertTrue(errMsg, row.value.startsWith(expectedStartsWith));
        }
    }

    // PRIVATE METHODS

    /**
     * Executes download verification. <code>searchPhrase</code> is used to
     * specify the search characters to send to the server. It may be null or empty.
     * @param testName the test name
     * @param facet the facet to test. If null, no facet is selected before the test.
     * @param searchString the search characters to be sent to the server. May
     *        be null or empty. If not empty, must be terminated by a trailing
     *        forward slash.
     * @return status
     */
    private void downloadTestEngine(String testName, String searchString) throws Exception {
        Date start = new Date();
        PageStatus status = new PageStatus();

        if (searchString == null)
            searchString = "";

        System.out.println("\n\n----- " + testName + " -----");

        try {
            // Apply searchPhrase. Click on this facet. Click on a random page. Click on each download type: Compare page values with download stream values.
            String target = baseUrl + "/search";
            logger.info("target: " + target);
            // target = "https://dev.mousephenotype.org/data/search?q=ranbp2#fq=*:*&facet=gene";
            SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO,
                    baseUrl);
            if (!searchString.isEmpty()) {
                searchPage.submitSearch(searchString + "\n");
            }

            SearchPage.Facet[] facets = { SearchPage.Facet.ANATOMY, SearchPage.Facet.DISEASES,
                    SearchPage.Facet.GENES, SearchPage.Facet.IMAGES, SearchPage.Facet.IMPC_IMAGES,
                    SearchPage.Facet.PHENOTYPES };

            for (SearchPage.Facet facet : facets) {
                if (searchPage.getFacetCount(facet) > 0) {
                    searchPage.clickFacet(facet);
                    searchPage.setNumEntries(SearchFacetTable.EntriesSelect._25);
                    searchPage.clickPageButton();
                    TestUtils.sleep(1000);
                    //searchPage.clickPageButton(SearchPage.PageDirective.FIFTH_NUMBERED);
                    //TestUtils.sleep(5000);
                    System.out.println("\nTesting " + facet + " facet. Search string: '" + searchString + "'. URL: "
                            + driver.getCurrentUrl());
                    status.add(searchPage.validateDownload(facet));
                }
            }
        } catch (Exception e) {
            String message = "EXCEPTION: SearchPageTest." + testName + "(): Message: " + e.getLocalizedMessage();
            System.out.println(message);
            e.printStackTrace();
            status.addError(message);
        } finally {
            if (status.hasErrors()) {
                errorList.add(status.toStringErrorMessages());
            } else {
                successList.add(testName + ": SUCCESS.");
            }

            TestUtils.printEpilogue(testName, start, errorList, exceptionList, successList, 1, 1);
        }
    }

    /**
     * Invokes the facet count engine with no search term.
     * @param target the page target URL
     * @return page status
     */
    private PageStatus facetCountEngine(String target) {
        return facetCountEngine(target, null);
    }

    /**
     * Invokes the facet count engine with the specified, [already escaped if necessary] search term.
     * @param target the page target URL
     * @param searchTerm the desired search term
     * @return page status
     */
    private PageStatus facetCountEngine(String target, SearchTermGroup searchTermGroup) {
        PageStatus status = new PageStatus();
        String message;

        //        System.out.println("facetCountEngine(): Page target URL: " + target);

        // Get the solarUrlCounts.
        Map solrCoreCountMap = getSolrCoreCounts(searchTermGroup);
        if (solrCoreCountMap == null) {
            message = "FAIL: Unable to get facet count from Solr.";
            status.addError(message);
            System.out.println(message);
            return status;
        }

        SearchPage searchPage = new SearchPage(driver, timeout_in_seconds, target, phenotypePipelineDAO, baseUrl);

        // Verify that the core counts returned by solr match the facet counts on the page and the page.
        for (String core : cores) {
            // 26-Mar-2015 (mrelac) Skip the core compare. The rules are fuzzy.
            if (core.equals(SearchPage.GENE_CORE)) {
                continue;
            }

            int facetCountFromPage = searchPage.getFacetCount(core);
            int facetCountFromSolr = (int) solrCoreCountMap.get(core);

            if (facetCountFromPage == facetCountFromSolr) {
                // Null statement.
            } else {
                message = "FAIL: facet count from Solr: " + facetCountFromSolr + ". facetCountFromPage: "
                        + facetCountFromPage + ". URL: " + target;
                status.addError(message);
                System.out.println(message);
            }
        }

        return status;
    }

    /**
     * Queries each of the six search solr cores for the number of occurrences
     * of <code>searchPhrase</code> (which may be null), returning a
     * <code>Map</code> keyed by core name containing the occurrence count for
     * each core.
     *
     * @param searchTermGroup The search phrase to use when querying the cores. If
     * null, the count is unfiltered.
     * @return the <code>searchPhrase</code> occurrence count
     */
    private Map<String, Integer> getSolrCoreCounts(SearchTermGroup searchTermGroup) {
        Map<String, Integer> solrCoreCountMap = new HashMap();

        for (int i = 0; i < paramList.size(); i++) {
            String solrQueryString = paramList.get(i);
            try {
                if (searchTermGroup != null) {
                    solrQueryString = solrQueryString.replace("&q=*:*", "&q=" + searchTermGroup.solrTarget);
                }

                String fqSolrQueryString = solrUrl + solrQueryString;

                JSONObject geneResults = JSONRestUtil.getResults(fqSolrQueryString);
                int facetCountFromSolr = geneResults.getJSONObject("response").getInt("numFound");
                String facet = cores.get(i);
                solrCoreCountMap.put(facet, facetCountFromSolr);
            } catch (TimeoutException te) {
                System.out.println("ERROR: SearchPageTest.getSolrCoreCounts() timeout!");
                return null;
            } catch (Exception e) {
                System.out.println("ERROR: SearchPageTest.getSolrCoreCounts(): " + e.getLocalizedMessage());
                return null;
            }
        }

        return solrCoreCountMap;
    }

    private void specialStrQueryTest(String testName, String qry) throws Exception {
        testCount++;

        System.out.println("\n\n----- " + testName + " -----");

        successList.clear();
        errorList.clear();

        driver.get(baseUrl + "/search?q=" + qry);

        new WebDriverWait(driver, 25).until(ExpectedConditions.elementToBeClickable(By.id("geneGrid_info")));
        String foundMsg = driver.findElement(By.cssSelector("span#resultCount a")).getText();
        if (foundMsg.isEmpty()) {
            System.out.println("[FAILED] - queried " + qry);
            sumErrorList.add("[FAILED] - queried " + qry);
            fail("There were " + sumErrorList.size() + " errors.");
        } else {
            System.out.println("[PASSED] - queried " + qry + ". Found " + foundMsg);
            sumSuccessList.add("passed");
        }
        System.out.println();
    }

}