Add UI tests for no-results-warnings

This commit is contained in:
TheOtherP 2018-01-23 18:30:59 +01:00
parent cf65f2ea78
commit a35b0ea98c
11 changed files with 649 additions and 277 deletions

View File

@ -9,11 +9,7 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.*;
import org.nzbhydra.NzbHydra;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -73,6 +69,7 @@ public class BaseConfig extends ValidatingConfig {
public void replace(BaseConfig newConfig) {
BaseConfig oldBaseConfig = null;
try {
//Easy way of cloning old config
oldBaseConfig = objectMapper.readValue(objectMapper.writeValueAsString(this), BaseConfig.class);
} catch (IOException e) {
logger.error("Error while creating copy of old config", e);
@ -85,7 +82,6 @@ public class BaseConfig extends ValidatingConfig {
searching = newConfig.getSearching();
auth = newConfig.getAuth();
ConfigChangedEvent configChangedEvent = new ConfigChangedEvent(this, oldBaseConfig, this);
applicationEventPublisher.publishEvent(configChangedEvent);
}

File diff suppressed because one or more lines are too long

View File

@ -123,14 +123,14 @@
</div>
</div>
<div class="row" ng-if="::indexersearches.length > 0 && numberOfAvailableResults === 0" style="margin-top: 50px">
<div class="row" ng-if="::indexersearches.length > 0 && (numberOfAvailableResults === 0 || numberOfAcceptedResults === 0)" style="margin-top: 50px" id="no-search-results">
<div class="well">
<h2 ng-if="!anyIndexersSearchedSuccessfully">Unable to search any indexer successfully; no results available</h2>
<h2 ng-if="!anyResultsRejected && anyIndexersSearchedSuccessfully">No results were found for this search</h2>
<h2 ng-if="anyResultsRejected">No (non-rejected) results were found for this search</h2>
</div>
</div>
<div class="row" ng-if="::indexersearches.length > 0 && numberOfAvailableResults > 0" style="margin-top: 10px" >
<div class="row" ng-if="::indexersearches.length > 0 && numberOfAvailableResults > 0 && numberOfAcceptedResults > 0" style="margin-top: 10px" >
<div class="col-md-8" style="text-align: left;">
<span id="display-options"
multiselect-dropdown options="optionsOptions" selected-model="optionsSelectedModel" settings="optionsExtraSettings" events="optionsEvents"

View File

@ -1,4 +1,4 @@
#Run like this: docker run -p <hostport>:5076 -v /home/ubuntu/dockertest/data/:/data -v /home/ubuntu/dockertest/torrents:/torrents nzbhydra2
#Run like this: docker run -p <hostport>:5076 -v /home/ubuntu/dockertest/data/:/data -v /home/ubuntu/dockertest/torrents:/torrents theotherp/nzbhydra2
#TODO: Automatically download latest release (see http://www.starkandwayne.com/blog/how-to-download-the-latest-release-from-github/) and use that
FROM alpine:edge

View File

@ -0,0 +1,109 @@
/*
* (C) Copyright 2017 TheOtherP (theotherp@gmx.de)
*
* 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.nzbhydra.config;
public final class DownloaderConfigBuilder {
private String apiKey = "apikey";
private String defaultCategory;
private DownloadType downloadType = DownloadType.NZB;
private boolean enabled = true;
private String iconCssClass;
private String name;
private NzbAddingType nzbAddingType = NzbAddingType.UPLOAD;
private DownloaderType downloaderType = DownloaderType.SABNZBD;
private String url = "http://127.0.0.1:7070";
private String username = "sab";
private String password = "nzbd";
private DownloaderConfigBuilder() {
}
public static DownloaderConfigBuilder builder() {
return new DownloaderConfigBuilder();
}
public DownloaderConfigBuilder apiKey(String apiKey) {
this.apiKey = apiKey;
return this;
}
public DownloaderConfigBuilder defaultCategory(String defaultCategory) {
this.defaultCategory = defaultCategory;
return this;
}
public DownloaderConfigBuilder downloadType(DownloadType downloadType) {
this.downloadType = downloadType;
return this;
}
public DownloaderConfigBuilder enabled(boolean enabled) {
this.enabled = enabled;
return this;
}
public DownloaderConfigBuilder iconCssClass(String iconCssClass) {
this.iconCssClass = iconCssClass;
return this;
}
public DownloaderConfigBuilder name(String name) {
this.name = name;
return this;
}
public DownloaderConfigBuilder nzbAddingType(NzbAddingType nzbAddingType) {
this.nzbAddingType = nzbAddingType;
return this;
}
public DownloaderConfigBuilder downloaderType(DownloaderType downloaderType) {
this.downloaderType = downloaderType;
return this;
}
public DownloaderConfigBuilder url(String url) {
this.url = url;
return this;
}
public DownloaderConfigBuilder username(String username) {
this.username = username;
return this;
}
public DownloaderConfigBuilder password(String password) {
this.password = password;
return this;
}
public DownloaderConfig build() {
DownloaderConfig downloaderConfig = new DownloaderConfig();
downloaderConfig.setApiKey(apiKey);
downloaderConfig.setDefaultCategory(defaultCategory);
downloaderConfig.setDownloadType(downloadType);
downloaderConfig.setEnabled(enabled);
downloaderConfig.setIconCssClass(iconCssClass);
downloaderConfig.setName(name);
downloaderConfig.setNzbAddingType(nzbAddingType);
downloaderConfig.setDownloaderType(downloaderType);
downloaderConfig.setUrl(url);
downloaderConfig.setUsername(username);
downloaderConfig.setPassword(password);
return downloaderConfig;
}
}

View File

@ -0,0 +1,221 @@
/*
* (C) Copyright 2017 TheOtherP (theotherp@gmx.de)
*
* 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.nzbhydra.config;
import org.nzbhydra.indexers.Indexer;
import org.nzbhydra.mapping.newznab.ActionAttribute;
import org.nzbhydra.mediainfo.InfoProvider;
import java.util.ArrayList;
import java.util.List;
public final class IndexerConfigBuilder {
private boolean allCapsChecked;
private String apiKey = "apikey";
private Indexer.BackendType backend = Indexer.BackendType.NEWZNAB;
private IndexerCategoryConfig categoryMapping = new IndexerCategoryConfig();
private boolean configComplete = true;
private List<String> enabledCategories = new ArrayList<>();
private Integer downloadLimit = null;
private boolean enabled = true;
private SearchSourceRestriction enabledForSearchSource = SearchSourceRestriction.BOTH;
private Integer generalMinSize = null;
private Integer hitLimit = null;
private Integer hitLimitResetTime = null;
private String host = "http://127.0.0.1:7070";
private Integer loadLimitOnRandom = null;
private String name = "indexer";
private String password = null;
private boolean preselect = true;
private List<String> schedule = new ArrayList<>();
private Integer score = null;
private SearchModuleType searchModuleType = SearchModuleType.NEWZNAB;
private boolean showOnSearch = true;
private List<InfoProvider.IdType> supportedSearchIds = new ArrayList<>();
private List<ActionAttribute> supportedSearchTypes = new ArrayList<>();
private Integer timeout = null;
private String username = null;
private String userAgent = null;
private IndexerConfigBuilder() {
}
public static IndexerConfigBuilder builder() {
return new IndexerConfigBuilder();
}
public IndexerConfigBuilder allCapsChecked(boolean allCapsChecked) {
this.allCapsChecked = allCapsChecked;
return this;
}
public IndexerConfigBuilder apiKey(String apiKey) {
this.apiKey = apiKey;
return this;
}
public IndexerConfigBuilder backend(Indexer.BackendType backend) {
this.backend = backend;
return this;
}
public IndexerConfigBuilder categoryMapping(IndexerCategoryConfig categoryMapping) {
this.categoryMapping = categoryMapping;
return this;
}
public IndexerConfigBuilder configComplete(boolean configComplete) {
this.configComplete = configComplete;
return this;
}
public IndexerConfigBuilder enabledCategories(List<String> enabledCategories) {
this.enabledCategories = enabledCategories;
return this;
}
public IndexerConfigBuilder downloadLimit(Integer downloadLimit) {
this.downloadLimit = downloadLimit;
return this;
}
public IndexerConfigBuilder enabled(boolean enabled) {
this.enabled = enabled;
return this;
}
public IndexerConfigBuilder enabledForSearchSource(SearchSourceRestriction enabledForSearchSource) {
this.enabledForSearchSource = enabledForSearchSource;
return this;
}
public IndexerConfigBuilder generalMinSize(Integer generalMinSize) {
this.generalMinSize = generalMinSize;
return this;
}
public IndexerConfigBuilder hitLimit(Integer hitLimit) {
this.hitLimit = hitLimit;
return this;
}
public IndexerConfigBuilder hitLimitResetTime(Integer hitLimitResetTime) {
this.hitLimitResetTime = hitLimitResetTime;
return this;
}
public IndexerConfigBuilder host(String host) {
this.host = host;
return this;
}
public IndexerConfigBuilder loadLimitOnRandom(Integer loadLimitOnRandom) {
this.loadLimitOnRandom = loadLimitOnRandom;
return this;
}
public IndexerConfigBuilder name(String name) {
this.name = name;
return this;
}
public IndexerConfigBuilder password(String password) {
this.password = password;
return this;
}
public IndexerConfigBuilder preselect(boolean preselect) {
this.preselect = preselect;
return this;
}
public IndexerConfigBuilder schedule(List<String> schedule) {
this.schedule = schedule;
return this;
}
public IndexerConfigBuilder score(Integer score) {
this.score = score;
return this;
}
public IndexerConfigBuilder searchModuleType(SearchModuleType searchModuleType) {
this.searchModuleType = searchModuleType;
return this;
}
public IndexerConfigBuilder showOnSearch(boolean showOnSearch) {
this.showOnSearch = showOnSearch;
return this;
}
public IndexerConfigBuilder supportedSearchIds(List<InfoProvider.IdType> supportedSearchIds) {
this.supportedSearchIds = supportedSearchIds;
return this;
}
public IndexerConfigBuilder supportedSearchTypes(List<ActionAttribute> supportedSearchTypes) {
this.supportedSearchTypes = supportedSearchTypes;
return this;
}
public IndexerConfigBuilder timeout(Integer timeout) {
this.timeout = timeout;
return this;
}
public IndexerConfigBuilder username(String username) {
this.username = username;
return this;
}
public IndexerConfigBuilder userAgent(String userAgent) {
this.userAgent = userAgent;
return this;
}
public IndexerConfig build() {
IndexerConfig indexerConfig = new IndexerConfig();
indexerConfig.setAllCapsChecked(allCapsChecked);
indexerConfig.setApiKey(apiKey);
indexerConfig.setBackend(backend);
indexerConfig.setCategoryMapping(categoryMapping);
indexerConfig.setConfigComplete(configComplete);
indexerConfig.setEnabledCategories(enabledCategories);
indexerConfig.setDownloadLimit(downloadLimit);
indexerConfig.setEnabled(enabled);
indexerConfig.setEnabledForSearchSource(enabledForSearchSource);
indexerConfig.setGeneralMinSize(generalMinSize);
indexerConfig.setHitLimit(hitLimit);
indexerConfig.setHitLimitResetTime(hitLimitResetTime);
indexerConfig.setHost(host);
indexerConfig.setLoadLimitOnRandom(loadLimitOnRandom);
indexerConfig.setName(name);
indexerConfig.setPassword(password);
indexerConfig.setPreselect(preselect);
indexerConfig.setSchedule(schedule);
indexerConfig.setScore(score);
indexerConfig.setSearchModuleType(searchModuleType);
indexerConfig.setShowOnSearch(showOnSearch);
indexerConfig.setSupportedSearchIds(supportedSearchIds);
indexerConfig.setSupportedSearchTypes(supportedSearchTypes);
indexerConfig.setTimeout(timeout);
indexerConfig.setUsername(username);
indexerConfig.setUserAgent(userAgent);
return indexerConfig;
}
}

View File

@ -1,24 +1,36 @@
package org.nzbhydra.tests;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import org.nzbhydra.config.BaseConfig;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
import java.net.URL;
public class AbstractConfigReplacingTest {
@Autowired
protected BaseConfig baseConfig;
public void replaceConfig(URL resource) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValueAsString(baseConfig);
ObjectReader updater = objectMapper.readerForUpdating(baseConfig);
BaseConfig updatedConfig = updater.readValue(resource);
baseConfig.replace(updatedConfig);
}
}
package org.nzbhydra.tests;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import org.nzbhydra.config.BaseConfig;
import org.nzbhydra.config.IndexerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
import java.net.URL;
import java.util.List;
public class AbstractConfigReplacingTest {
@Autowired
protected BaseConfig baseConfig;
public void replaceConfig(URL resource) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValueAsString(baseConfig);
ObjectReader updater = objectMapper.readerForUpdating(baseConfig);
BaseConfig updatedConfig = updater.readValue(resource);
baseConfig.replace(updatedConfig);
}
public void replaceConfig(BaseConfig replacingConfig) throws IOException {
baseConfig.replace(replacingConfig);
}
public void replaceIndexers(List<IndexerConfig> indexerConfigs) throws IOException {
baseConfig.getIndexers().clear();
baseConfig.getIndexers().addAll(indexerConfigs);
baseConfig.replace(baseConfig);
}
}

View File

@ -1,59 +1,59 @@
package org.nzbhydra.tests.pageobjects;
import org.popper.fw.annotations.Page;
import org.popper.fw.element.IButton;
import org.popper.fw.element.ILabel;
import org.popper.fw.element.ILink;
import org.popper.fw.element.ITextBox;
import org.popper.fw.webdriver.annotations.PageAccessor;
import org.popper.fw.webdriver.annotations.locator.Locator;
import java.util.List;
@Page
public interface SearchPO {
@PageAccessor(uri = "/")
public void open();
@Locator(id = "searchCategoryDropdownButton")
public IButton categoryToggleButton();
@Locator(cssSelector = ".search-category-option")
public List<ILink> categoryOptions();
@Locator(id = "by-id")
public ICheckBox byIdCheckbox();
@Locator(id = "clear-autocomplete-button")
public IButton clearAutocompleteButton();
@Locator(id = "selected-item-title")
public ILabel selectedItemTitle();
@Locator(id = "seriesSearchS")
public ITextBox seasonField();
@Locator(id = "seriesSearchE")
public ITextBox episodeField();
@Locator(id = "searchfield")
public ITextBox searchField();
@Locator(id = "history-dropdown-button")
public IButton historyDropdownButton();
@Locator(cssSelector = ".search-history-dropdown-entry")
public List<ILink> searchHistoryEntries();
@Locator(id = "startsearch")
public IButton goButton();
@Locator(cssSelector = ".indexer-selection-button")
public IIndexerSelectionButton indexerSelectionButton();
@Locator(cssSelector = ".indexer-selection-checkbox")
public List<ICheckBox> indexerSelectionCheckboxes();
}
package org.nzbhydra.tests.pageobjects;
import org.popper.fw.annotations.Page;
import org.popper.fw.element.IButton;
import org.popper.fw.element.ILabel;
import org.popper.fw.element.ILink;
import org.popper.fw.element.ITextBox;
import org.popper.fw.webdriver.annotations.PageAccessor;
import org.popper.fw.webdriver.annotations.locator.Locator;
import java.util.List;
@Page
public interface SearchPO {
@PageAccessor(uri = "/")
public void open();
@Locator(id = "searchCategoryDropdownButton")
public IButton categoryDropdownButton();
@Locator(cssSelector = ".search-category-option")
public List<ILink> categoryOptions();
@Locator(id = "by-id")
public ICheckBox byIdCheckbox();
@Locator(id = "clear-autocomplete-button")
public IButton clearAutocompleteButton();
@Locator(id = "selected-item-title")
public ILabel selectedItemTitle();
@Locator(id = "seriesSearchS")
public ITextBox seasonField();
@Locator(id = "seriesSearchE")
public ITextBox episodeField();
@Locator(id = "searchfield")
public ITextBox searchField();
@Locator(id = "history-dropdown-button")
public IButton historyDropdownButton();
@Locator(cssSelector = ".search-history-dropdown-entry")
public List<ILink> searchHistoryEntries();
@Locator(id = "startsearch")
public IButton goButton();
@Locator(cssSelector = ".indexer-selection-button")
public IIndexerSelectionButton indexerSelectionButton();
@Locator(cssSelector = ".indexer-selection-checkbox")
public List<ICheckBox> indexerSelectionCheckboxes();
}

View File

@ -1,152 +1,155 @@
package org.nzbhydra.tests.pageobjects;
import org.popper.fw.annotations.Page;
import org.popper.fw.element.IButton;
import org.popper.fw.element.ILabel;
import org.popper.fw.webdriver.annotations.locator.Locator;
import java.util.List;
import java.util.stream.Collectors;
@Page
public abstract class SearchResultsPO {
@Locator(id = "display-options")
public abstract IDropdownCheckboxButton displayOptions();
@Locator(id = "search-results-selection-button")
public abstract ISelectionButton searchResultSelectionButton();
@Locator(id = "send-selected-to-downloader")
public abstract IButton sendSelectedToDownloaderButton();
@Locator(id = "send-selected-to-downloader-dropdown")
public abstract IButton sendSelectedToDownloaderDropdown();
@Locator(cssSelector = ".send-to-downloader")
public abstract List<ILink> sendToDownloaderButtons();
@Locator(id = "download-selected-as-zip")
public abstract IButton downloadSelectedAsZipButton();
@Locator(cssSelector = ".search-results-header-row")
public abstract TableHeader tableHeader();
@Locator(cssSelector = ".search-result-row")
public abstract List<SearchResultRow> searchResultRows();
@Locator(cssSelector = ".result-checkbox")
public abstract List<ICheckBox> indexerSelectionCheckboxes();
@Locator(cssSelector = ".title-expand-toggle")
public abstract List<IToggle> titleGroupToggles();
@Locator(cssSelector = ".duplicate-expand-toggle")
public abstract List<IToggle> duplicateGroupToggles();
public List<String> titles() {
return searchResultRows().stream().map(x -> x.title().text().trim()).collect(Collectors.toList());
}
public List<String> indexers() {
return searchResultRows().stream().map(x -> x.indexer().text().trim()).collect(Collectors.toList());
}
public List<String> categories() {
return searchResultRows().stream().map(x -> x.category().text().trim()).collect(Collectors.toList());
}
public List<String> sizes() {
return searchResultRows().stream().map(x -> x.size().text().trim()).collect(Collectors.toList());
}
public List<String> grabs() {
return searchResultRows().stream().map(x -> x.grabs().text().trim()).collect(Collectors.toList());
}
public List<String> ages() {
return searchResultRows().stream().map(x -> x.age().text().trim()).collect(Collectors.toList());
}
public interface TableHeader {
@Locator(cssSelector = ".column-sortable-title")
IColumnSortable titleHeader();
@Locator(cssSelector = ".search-results-header-row .result-title .filter-wrapper")
IFreetextFilter titleFilter();
@Locator(cssSelector = ".column-sortable-indexer")
IColumnSortable indexerHeader();
@Locator(cssSelector = ".search-results-header-row .result-indexer .filter-wrapper")
ICheckboxFilter indexerFilter();
@Locator(cssSelector = ".column-sortable-category")
IColumnSortable categoryHeader();
@Locator(cssSelector = ".search-results-header-row .result-category .filter-wrapper")
ICheckboxFilter categoryFilter();
@Locator(cssSelector = ".column-sortable-size")
IColumnSortable sizeHeader();
@Locator(cssSelector = ".search-results-header-row .result-size .filter-wrapper")
INumberRangeFilter sizeFilter();
@Locator(cssSelector = ".column-sortable-grabs")
IColumnSortable grabsHeader();
@Locator(cssSelector = ".search-results-header-row .result-details .filter-wrapper")
INumberRangeFilter grabsFilter();
@Locator(cssSelector = ".column-sortable-epoch")
IColumnSortable ageHeader();
@Locator(cssSelector = ".search-results-header-row .result-age .filter-wrapper")
INumberRangeFilter ageFilter();
}
public interface SearchResultRow {
//Later Support for duplicate rows
@Locator(cssSelector = ".result-title .title")
ILabel title();
@Locator(cssSelector = ".result-indexer")
ILabel indexer();
@Locator(cssSelector = ".result-category")
ILabel category();
@Locator(cssSelector = ".result-size")
ILabel size();
@Locator(cssSelector = ".result-details")
ILabel grabs();
@Locator(cssSelector = ".result-age")
ILabel age();
@Locator(cssSelector = ".result-show-nfo-link")
org.nzbhydra.tests.pageobjects.ILink showNfoButton();
@Locator(cssSelector = ".result-comments-link")
org.nzbhydra.tests.pageobjects.ILink commentsLink();
@Locator(cssSelector = ".result-details-link")
org.nzbhydra.tests.pageobjects.ILink detailsLink();
@Locator(cssSelector = ".result-torrent-download-link")
org.nzbhydra.tests.pageobjects.ILink downloadTorrentLink();
@Locator(cssSelector = ".result-nzb-download-link")
org.nzbhydra.tests.pageobjects.ILink downloadNzbLink();
@Locator(cssSelector = ".result-send-to-downloader-link")
List<org.nzbhydra.tests.pageobjects.ILink> sendToDownloaderButtons();
}
}
package org.nzbhydra.tests.pageobjects;
import org.popper.fw.annotations.Page;
import org.popper.fw.element.IButton;
import org.popper.fw.element.ILabel;
import org.popper.fw.webdriver.annotations.locator.Locator;
import java.util.List;
import java.util.stream.Collectors;
@Page
public abstract class SearchResultsPO {
@Locator(id="no-search-results")
public abstract ILabel noSearchResultsWarning();
@Locator(id = "display-options")
public abstract IDropdownCheckboxButton displayOptions();
@Locator(id = "search-results-selection-button")
public abstract ISelectionButton searchResultSelectionButton();
@Locator(id = "send-selected-to-downloader")
public abstract IButton sendSelectedToDownloaderButton();
@Locator(id = "send-selected-to-downloader-dropdown")
public abstract IButton sendSelectedToDownloaderDropdown();
@Locator(cssSelector = ".send-to-downloader")
public abstract List<ILink> sendToDownloaderButtons();
@Locator(id = "download-selected-as-zip")
public abstract IButton downloadSelectedAsZipButton();
@Locator(cssSelector = ".search-results-header-row")
public abstract TableHeader tableHeader();
@Locator(cssSelector = ".search-result-row")
public abstract List<SearchResultRow> searchResultRows();
@Locator(cssSelector = ".result-checkbox")
public abstract List<ICheckBox> indexerSelectionCheckboxes();
@Locator(cssSelector = ".title-expand-toggle")
public abstract List<IToggle> titleGroupToggles();
@Locator(cssSelector = ".duplicate-expand-toggle")
public abstract List<IToggle> duplicateGroupToggles();
public List<String> titles() {
return searchResultRows().stream().map(x -> x.title().text().trim()).collect(Collectors.toList());
}
public List<String> indexers() {
return searchResultRows().stream().map(x -> x.indexer().text().trim()).collect(Collectors.toList());
}
public List<String> categories() {
return searchResultRows().stream().map(x -> x.category().text().trim()).collect(Collectors.toList());
}
public List<String> sizes() {
return searchResultRows().stream().map(x -> x.size().text().trim()).collect(Collectors.toList());
}
public List<String> grabs() {
return searchResultRows().stream().map(x -> x.grabs().text().trim()).collect(Collectors.toList());
}
public List<String> ages() {
return searchResultRows().stream().map(x -> x.age().text().trim()).collect(Collectors.toList());
}
public interface TableHeader {
@Locator(cssSelector = ".column-sortable-title")
IColumnSortable titleHeader();
@Locator(cssSelector = ".search-results-header-row .result-title .filter-wrapper")
IFreetextFilter titleFilter();
@Locator(cssSelector = ".column-sortable-indexer")
IColumnSortable indexerHeader();
@Locator(cssSelector = ".search-results-header-row .result-indexer .filter-wrapper")
ICheckboxFilter indexerFilter();
@Locator(cssSelector = ".column-sortable-category")
IColumnSortable categoryHeader();
@Locator(cssSelector = ".search-results-header-row .result-category .filter-wrapper")
ICheckboxFilter categoryFilter();
@Locator(cssSelector = ".column-sortable-size")
IColumnSortable sizeHeader();
@Locator(cssSelector = ".search-results-header-row .result-size .filter-wrapper")
INumberRangeFilter sizeFilter();
@Locator(cssSelector = ".column-sortable-grabs")
IColumnSortable grabsHeader();
@Locator(cssSelector = ".search-results-header-row .result-details .filter-wrapper")
INumberRangeFilter grabsFilter();
@Locator(cssSelector = ".column-sortable-epoch")
IColumnSortable ageHeader();
@Locator(cssSelector = ".search-results-header-row .result-age .filter-wrapper")
INumberRangeFilter ageFilter();
}
public interface SearchResultRow {
//Later Support for duplicate rows
@Locator(cssSelector = ".result-title .title")
ILabel title();
@Locator(cssSelector = ".result-indexer")
ILabel indexer();
@Locator(cssSelector = ".result-category")
ILabel category();
@Locator(cssSelector = ".result-size")
ILabel size();
@Locator(cssSelector = ".result-details")
ILabel grabs();
@Locator(cssSelector = ".result-age")
ILabel age();
@Locator(cssSelector = ".result-show-nfo-link")
org.nzbhydra.tests.pageobjects.ILink showNfoButton();
@Locator(cssSelector = ".result-comments-link")
org.nzbhydra.tests.pageobjects.ILink commentsLink();
@Locator(cssSelector = ".result-details-link")
org.nzbhydra.tests.pageobjects.ILink detailsLink();
@Locator(cssSelector = ".result-torrent-download-link")
org.nzbhydra.tests.pageobjects.ILink downloadTorrentLink();
@Locator(cssSelector = ".result-nzb-download-link")
org.nzbhydra.tests.pageobjects.ILink downloadNzbLink();
@Locator(cssSelector = ".result-send-to-downloader-link")
List<org.nzbhydra.tests.pageobjects.ILink> sendToDownloaderButtons();
}
}

View File

@ -10,6 +10,8 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.nzbhydra.config.IndexerConfigBuilder;
import org.nzbhydra.config.SearchSourceRestriction;
import org.nzbhydra.downloading.NzbHandler.NzbsZipResponse;
import org.nzbhydra.mapping.newznab.builder.RssItemBuilder;
import org.nzbhydra.mapping.newznab.mock.NewznabMockBuilder;
@ -22,28 +24,7 @@ import org.nzbhydra.searching.SearchRepository;
import org.nzbhydra.searching.searchrequests.SearchRequest.SearchSource;
import org.nzbhydra.tests.AbstractConfigReplacingTest;
import org.nzbhydra.tests.NzbhydraMockMvcTest;
import org.nzbhydra.tests.pageobjects.CheckBox;
import org.nzbhydra.tests.pageobjects.CheckboxFilter;
import org.nzbhydra.tests.pageobjects.ColumnSortable;
import org.nzbhydra.tests.pageobjects.DropdownCheckboxButton;
import org.nzbhydra.tests.pageobjects.FreetextFilter;
import org.nzbhydra.tests.pageobjects.ICheckBox;
import org.nzbhydra.tests.pageobjects.ICheckboxFilter;
import org.nzbhydra.tests.pageobjects.IColumnSortable;
import org.nzbhydra.tests.pageobjects.IDropdownCheckboxButton;
import org.nzbhydra.tests.pageobjects.IFreetextFilter;
import org.nzbhydra.tests.pageobjects.IIndexerSelectionButton;
import org.nzbhydra.tests.pageobjects.ILink;
import org.nzbhydra.tests.pageobjects.INumberRangeFilter;
import org.nzbhydra.tests.pageobjects.ISelectionButton;
import org.nzbhydra.tests.pageobjects.IToggle;
import org.nzbhydra.tests.pageobjects.IndexerSelectionButton;
import org.nzbhydra.tests.pageobjects.Link;
import org.nzbhydra.tests.pageobjects.NumberRangeFilter;
import org.nzbhydra.tests.pageobjects.SearchPO;
import org.nzbhydra.tests.pageobjects.SearchResultsPO;
import org.nzbhydra.tests.pageobjects.SelectionButton;
import org.nzbhydra.tests.pageobjects.Toggle;
import org.nzbhydra.tests.pageobjects.*;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
@ -164,10 +145,11 @@ public class SearchingResultsUiTest extends AbstractConfigReplacingTest {
assertThat(searchPage.indexerSelectionCheckboxes().get(1).ischecked()).isFalse();
assertThat(searchPage.indexerSelectionCheckboxes().get(2).ischecked()).isTrue();
searchPage.categoryToggleButton().click();
searchPage.categoryDropdownButton().click();
searchPage.categoryOptions().stream().filter(x -> x.text().equals("Anime")).findFirst().get().click();
assertThat(searchPage.categoryDropdownButton().text()).isEqualTo("Anime");
assertThat(searchPage.indexerSelectionCheckboxes().stream().map(x -> x.getAttribute("indexer-name")).collect(Collectors.toList())).as("Should've removed mock2 because it's not enabled for Anime category").containsExactly("mock1", "mock3");
searchPage.categoryToggleButton().click();
searchPage.categoryDropdownButton().click();
searchPage.categoryOptions().stream().filter(x -> x.text().equals("Movies")).findFirst().get().click();
assertThat(searchPage.indexerSelectionCheckboxes().stream().map(x -> x.getAttribute("indexer-name")).collect(Collectors.toList())).containsExactly("mock1", "mock2", "mock3");
}
@ -390,6 +372,54 @@ public class SearchingResultsUiTest extends AbstractConfigReplacingTest {
assertThat(searchResultsPage.ages()).containsExactly("1d", "2d", "3d").as("Title groups should be sorted internally as well");
}
@Test
public void testMessageIfNoResults() throws Exception {
replaceIndexers(Arrays.asList(IndexerConfigBuilder.builder().build()));
NewznabXmlRoot rssRoot = NewznabMockBuilder.getRssRoot(Arrays.asList(), 0, 0);
mockWebServer.enqueue(new MockResponse().setBody(rssRoot.toXmlString()).setHeader("Content-Type", "application/xml; charset=utf-8"));
webDriver.get(url + "/?category=All&query=uitest&mode=search");
WebDriverWait wait = new WebDriverWait(webDriver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("no-search-results")));
SearchResultsPO searchResultsPage = factory.createPage(SearchResultsPO.class);
assertThat(searchResultsPage.noSearchResultsWarning().text()).isEqualTo("No results were found for this search");
assertThat(webDriver.findElements(By.className("search-results-table")).isEmpty()).isTrue();
}
@Test
public void testMessageIfNoIndexerSuccessful() throws Exception {
replaceIndexers(Arrays.asList(IndexerConfigBuilder.builder().build()));
mockWebServer.enqueue(new MockResponse().setResponseCode(400));
webDriver.get(url + "/?category=All&query=uitest&mode=search");
WebDriverWait wait = new WebDriverWait(webDriver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("no-search-results")));
SearchResultsPO searchResultsPage = factory.createPage(SearchResultsPO.class);
assertThat(searchResultsPage.noSearchResultsWarning().text()).isEqualTo("Unable to search any indexer successfully; no results available");
assertThat(webDriver.findElements(By.className("search-results-table")).isEmpty()).isTrue();
}
@Test
public void testMessageIfAllResultsRejected() throws Exception {
replaceIndexers(Arrays.asList(IndexerConfigBuilder.builder().build()));
baseConfig.getSearching().setRequiredWords(Collections.singletonList("not in there"));
baseConfig.getSearching().setApplyRestrictions(SearchSourceRestriction.INTERNAL);
replaceConfig(baseConfig);
NewznabXmlRoot rssRoot = NewznabMockBuilder.getRssRoot(Arrays.asList(RssItemBuilder.builder("someresult").build()), 0, 1);
mockWebServer.enqueue(new MockResponse().setBody(rssRoot.toXmlString()).setHeader("Content-Type", "application/xml; charset=utf-8"));
webDriver.get(url + "/?category=All&query=uitest&mode=search");
WebDriverWait wait = new WebDriverWait(webDriver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("no-search-results")));
SearchResultsPO searchResultsPage = factory.createPage(SearchResultsPO.class);
assertThat(searchResultsPage.noSearchResultsWarning().text()).isEqualTo("No (non-rejected) results were found for this search");
assertThat(webDriver.findElements(By.className("search-results-table")).isEmpty()).isTrue();
}
protected void prepareFiveResultsFromTwoIndexers() throws Exception {
replaceConfig(getClass().getResource("twoIndexers.json"));

View File

@ -19,4 +19,5 @@ server.port=5077
main.port=5077
main.theme=grey
main.host=127.0.0.1
main.api-key=apikey
main.api-key=apikey
main.welcome-shown=true