diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 16668ed4..76cc31a7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,10 +3,12 @@ groovy-version = "3.0.17" junit5-version = "5.10.1" [libraries] +commons-validator = "commons-validator:commons-validator:1.8.0" # Use Groovy which corresponds to Gradle version (of hsc build) groovy-bom = { module = "org.codehaus.groovy:groovy-bom", version.ref = "groovy-version" } jsoup = "org.jsoup:jsoup:1.17.2" junit-vintage = { module = "org.junit.vintage:junit-vintage-engine", version.ref = "junit5-version" } +lombok = "org.projectlombok:lombok:1.18.30" slf4j-api = "org.slf4j:slf4j-api:2.0.11" slf4j-nop = "org.slf4j:slf4j-nop:2.0.11" spock = "org.spockframework:spock-bom:2.3-groovy-3.0" diff --git a/htmlSanityCheck-core/build.gradle b/htmlSanityCheck-core/build.gradle index 8a5898f9..acc3b3b1 100644 --- a/htmlSanityCheck-core/build.gradle +++ b/htmlSanityCheck-core/build.gradle @@ -1,13 +1,21 @@ import org.apache.tools.ant.filters.ReplaceTokens dependencies { + implementation (libs.commons.validator) { + // Having a vulnerability here ... + exclude group: 'commons-collections', module: 'commons-collections' + } implementation libs.slf4j.api testImplementation libs.slf4j.nop // jsoup is our awesome html parser, see jsoup.org implementation libs.jsoup + + compileOnly libs.lombok + annotationProcessor libs.lombok + testCompileOnly libs.lombok + testAnnotationProcessor libs.lombok + implementation 'org.codehaus.groovy:groovy-xml' - // Since Groovy 2.5 it is necessary to import dateutil separately - implementation 'org.codehaus.groovy:groovy-dateutil' } publishing { diff --git a/htmlSanityCheck-core/src/main/groovy/org/aim42/filesystem/FileUtil.groovy b/htmlSanityCheck-core/src/main/groovy/org/aim42/filesystem/FileUtil.groovy index 1f34d7cc..90041df4 100644 --- a/htmlSanityCheck-core/src/main/groovy/org/aim42/filesystem/FileUtil.groovy +++ b/htmlSanityCheck-core/src/main/groovy/org/aim42/filesystem/FileUtil.groovy @@ -25,7 +25,7 @@ import java.nio.file.Path class FileUtil { - static File commonPath(Collection files) { + static File commonPath(Set files) { if (!files) { return null } diff --git a/htmlSanityCheck-core/src/main/groovy/org/aim42/htmlsanitycheck/AllChecksRunner.groovy b/htmlSanityCheck-core/src/main/groovy/org/aim42/htmlsanitycheck/AllChecksRunner.groovy index b73e6ddd..aaf7d5e8 100644 --- a/htmlSanityCheck-core/src/main/groovy/org/aim42/htmlsanitycheck/AllChecksRunner.groovy +++ b/htmlSanityCheck-core/src/main/groovy/org/aim42/htmlsanitycheck/AllChecksRunner.groovy @@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory class AllChecksRunner { // we check a collection of files: - private Collection filesToCheck = new HashSet() + private Set filesToCheck = new HashSet() // where do we put our results private File checkingResultsDir @@ -45,7 +45,7 @@ class AllChecksRunner { boolean consoleReport = true // checker instances - private Set checkers + private List checkers // keep all results private PerRunResults resultsForAllPages @@ -55,29 +55,29 @@ class AllChecksRunner { private Configuration myConfig - private static final Logger logger = LoggerFactory.getLogger(AllChecksRunner.class); + private static final Logger logger = LoggerFactory.getLogger(AllChecksRunner.class) /** * runs all available checks * */ - public AllChecksRunner( Configuration pConfig ) { + AllChecksRunner( Configuration pConfig ) { super() myConfig = pConfig - this.filesToCheck = myConfig.getConfigItemByName(Configuration.ITEM_NAME_sourceDocuments) + this.filesToCheck = myConfig.getSourceDocuments() // TODO: #185 (checker classes shall be detected automatically (aka CheckerFactory) // CheckerFactory needs the configuration - Set checkerClasses = myConfig.getConfigItemByName(Configuration.ITEM_NAME_checksToExecute) + List checkerClasses = myConfig.getChecksToExecute() this.checkers = CheckerCreator.createCheckerClassesFrom( checkerClasses, myConfig ) this.resultsForAllPages = new PerRunResults() - this.checkingResultsDir = myConfig.getConfigItemByName(Configuration.ITEM_NAME_checkingResultsDir) - this.junitResultsDir = myConfig.getConfigItemByName(Configuration.ITEM_NAME_junitResultsDir) + this.checkingResultsDir = myConfig.getCheckingResultsDir() + this.junitResultsDir = myConfig.getJunitResultsDir() logger.debug("AllChecksRunner created with ${this.checkers.size()} checkers for ${filesToCheck.size()} files") } @@ -88,7 +88,7 @@ class AllChecksRunner { * performs all available checks on pageToCheck * */ - public PerRunResults performAllChecks() { + PerRunResults performAllChecks() { logger.debug "entered performAllChecks" @@ -191,7 +191,7 @@ class AllChecksRunner { * line with default settings... * @param args */ - public static void main(String[] args) { + static void main(String[] args) { // TODO: read parameter from command line // empty method is currently marked "prio-2" issue by CodeNarc... we'll ignore that diff --git a/htmlSanityCheck-core/src/main/java/net/ricecode/similarity/StringSimilarityServiceImpl.java b/htmlSanityCheck-core/src/main/java/net/ricecode/similarity/StringSimilarityServiceImpl.java index d47ec891..4464863f 100644 --- a/htmlSanityCheck-core/src/main/java/net/ricecode/similarity/StringSimilarityServiceImpl.java +++ b/htmlSanityCheck-core/src/main/java/net/ricecode/similarity/StringSimilarityServiceImpl.java @@ -24,7 +24,6 @@ package net.ricecode.similarity; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -57,7 +56,7 @@ public StringSimilarityServiceImpl(SimilarityStrategy strategy) { * @return A list of similarity scores. */ public List scoreAll(List features, String target) { - ArrayList scores = new ArrayList(); + List scores = new ArrayList<>(); for (String feature : features) { double score = strategy.score(feature, target); @@ -99,11 +98,11 @@ public SimilarityScore findTop(List features, String target) { * @return A SimilarityScore that has the top value amongst the features, according to the comparator. */ public SimilarityScore findTop(List features, String target, Comparator comparator) { - if (features.size() == 0) { + if (features.isEmpty()) { return null; } List scores = scoreAll(features, target); - Collections.sort(scores, comparator); + scores.sort(comparator); return scores.get(0); } @@ -119,11 +118,11 @@ public SimilarityScore findTop(List features, String target, Comparator< * according to the comparator */ public List findBestN(List features, String target, int n) { - List result = new ArrayList(); + List result = new ArrayList<>(); - if ((features.size() > 0) && (n >= 1)) { + if ((!features.isEmpty()) && (n >= 1)) { List scores = scoreAll(features, target); - Collections.sort(scores, new DescendingSimilarityScoreComparator()); + scores.sort(new DescendingSimilarityScoreComparator()); // fails if n> scores.size(): result = scores.subList(0, n); result = scores.subList(0, Math.min(scores.size(), n)); diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/Configuration.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/Configuration.java index cc81f81f..098bcd6c 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/Configuration.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/Configuration.java @@ -1,308 +1,158 @@ package org.aim42.htmlsanitycheck; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; import org.aim42.htmlsanitycheck.check.AllCheckers; +import org.aim42.htmlsanitycheck.check.Checker; import org.aim42.htmlsanitycheck.tools.Web; import java.io.File; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.HashSet; +import java.util.List; import java.util.Set; /** * Handles (and can verify) configuration options. *

- * Implemented as REGISTRY pattern - *

- *

- * Explanation for configuring http status codes: - * The standard http status codes are defined in class @link NetUtil and can - * be overwritten by configuration: - *

- * Example: You want 503 to be ok instead of error: - * httpSuccessCodes = [503] - *

- * During configuration initialization, the value(s) of httpSuccessCodes will be: - * 1.) set-added to httpSuccessCodes, - * 2.) set-subtracted from the warnings and errors. - *

- *

- * This class needs to be updated if additional configuration options are added. - *

- *

* Ideas for additional config options: * ------------------------------------ * - verbosity level on console during checks + * - exclusion lists for hosts or particular URLs */ +@Getter +@Builder +@AllArgsConstructor +@ToString +@Slf4j public class Configuration { - /***************************************** - * configuration item names - * - * NEVER use any string constants for configuration - * item names within source code! - ****************************************/ - private static final String ITEM_NAME_sourceDocuments = "sourceDocuments"; - private static final String ITEM_NAME_sourceDir = "sourceDir"; - private static final String ITEM_NAME_checkingResultsDir = "checkingResultsDir"; - private static final String ITEM_NAME_junitResultsDir = "junitResultsDir"; - private static final String ITEM_NAME_consoleReport = "consoleReport"; - private static final String ITEM_NAME_failOnErrors = "failOnErrors"; - private static final String ITEM_NAME_httpConnectionTimeout = "httpConnectionTimeout"; - private static final String ITEM_NAME_ignoreLocalhost = "ignoreLocalHost"; - private static final String ITEM_NAME_ignoreIPAddresses = "ignoreIPAddresses"; - private static final String ITEM_NAME_httpWarningCodes = "httpWarningCodes"; - private static final String ITEM_NAME_httpErrorCodes = "httpErrorCodes"; - private static final String ITEM_NAME_httpSuccessCodes = "httpSuccessCodes"; - private static final String ITEM_NAME_urlsToExclude = "urlsToExclude"; - private static final String ITEM_NAME_hostsToExclude = "hostsToExclude"; - private static final String ITEM_NAME_prefixOnlyHrefExtensions = "prefixOnlyHrefExtensions"; - private static final String ITEM_NAME_checksToExecute = "checksToExecute"; - /*************************** - * private member - **************************/ - private final Map configurationItems = new LinkedHashMap(); - - public Configuration() { - - this.configurationItems.put(ITEM_NAME_httpErrorCodes, Web.HTTP_ERROR_CODES); - this.configurationItems.put(ITEM_NAME_httpSuccessCodes, Web.HTTP_SUCCESS_CODES); - this.configurationItems.put(ITEM_NAME_httpWarningCodes, Web.HTTP_WARNING_CODES); - - this.configurationItems.put(ITEM_NAME_httpConnectionTimeout, 5000);// 5 secs as default timeout - this.configurationItems.put(ITEM_NAME_ignoreIPAddresses, false);// warning if numerical IP addresses - this.configurationItems.put(ITEM_NAME_ignoreLocalhost, false);// warning if localhost-URLs - - this.configurationItems.put(ITEM_NAME_prefixOnlyHrefExtensions, Web.POSSIBLE_EXTENSIONS); - - this.configurationItems.put(ITEM_NAME_checksToExecute, AllCheckers.checkerClazzes); - } - - public static String getITEM_NAME_sourceDocuments() { - return ITEM_NAME_sourceDocuments; - } - - public static String getITEM_NAME_sourceDir() { - return ITEM_NAME_sourceDir; - } - - public static String getITEM_NAME_checkingResultsDir() { - return ITEM_NAME_checkingResultsDir; - } - - public static String getITEM_NAME_junitResultsDir() { - return ITEM_NAME_junitResultsDir; - } - - public static String getITEM_NAME_consoleReport() { - return ITEM_NAME_consoleReport; - } - - public static String getITEM_NAME_failOnErrors() { - return ITEM_NAME_failOnErrors; - } - - public static String getITEM_NAME_httpConnectionTimeout() { - return ITEM_NAME_httpConnectionTimeout; - } - - public static String getITEM_NAME_ignoreLocalhost() { - return ITEM_NAME_ignoreLocalhost; - } - - public static String getITEM_NAME_ignoreIPAddresses() { - return ITEM_NAME_ignoreIPAddresses; - } - - public static String getITEM_NAME_httpWarningCodes() { - return ITEM_NAME_httpWarningCodes; - } - - public static String getITEM_NAME_httpErrorCodes() { - return ITEM_NAME_httpErrorCodes; - } - - public static String getITEM_NAME_httpSuccessCodes() { - return ITEM_NAME_httpSuccessCodes; - } - - public static String getITEM_NAME_urlsToExclude() { - return ITEM_NAME_urlsToExclude; - } - - public static String getITEM_NAME_hostsToExclude() { - return ITEM_NAME_hostsToExclude; - } - - public static String getITEM_NAME_prefixOnlyHrefExtensions() { - return ITEM_NAME_prefixOnlyHrefExtensions; - } - - public static String getITEM_NAME_checksToExecute() { - return ITEM_NAME_checksToExecute; - } - - /** - * retrieve a single configuration item - * - * @param itemName - * @return + Set sourceDocuments; + File sourceDir; + File checkingResultsDir; + File junitResultsDir; + Boolean consoleReport; + Boolean failOnErrors; + Integer httpConnectionTimeout; + Boolean ignoreLocalhost; + Boolean ignoreIPAddresses; + /* + * Explanation for configuring http status codes: + * The standard http status codes are defined in class @link NetUtil and can + * be overwritten by configuration: + *

+ * Example: You want 503 to be ok instead of error: + * httpSuccessCodes = [503] + *

+ * During configuration initialization, the value(s) of httpSuccessCodes will be: + * 1.) set-added to httpSuccessCodes, + * 2.) set-subtracted from the warnings and errors. */ - public synchronized Object getConfigItemByName(final String itemName) { - return configurationItems.get(itemName); - } - - public Set getConfigItemByNameSetOfIntegers(final String itemName) { - Object rawConfig = getConfigItemByName(itemName); - if (rawConfig instanceof Set ) { - return (Set) rawConfig; - } - throw new IllegalArgumentException("The Configuration property \"" + itemName + "\" should be a set of integers"); - } + // Make modifiable copies! + final Set httpWarningCodes = new HashSet<>(Web.HTTP_WARNING_CODES); + final Set httpErrorCodes = new HashSet<>(Web.HTTP_ERROR_CODES); + final Set httpSuccessCodes = new HashSet<>(Web.HTTP_SUCCESS_CODES); + Set prefixOnlyHrefExtensions; + List> checksToExecute; - /** - * convenience method for simplified testing - */ - public synchronized void addSourceFileConfiguration(File srcDir, Collection srcDocs) { - addConfigurationItem(ITEM_NAME_sourceDir, srcDir); - addConfigurationItem(ITEM_NAME_sourceDocuments, srcDocs); - } - - /** - * @return true if item is already present, false otherwise - */ - public boolean checkIfItemPresent(String itemName) { - return configurationItems.get(itemName) != null; + public Configuration() { + this.httpConnectionTimeout = 5000;// 5 secs as default timeout + this.ignoreIPAddresses = false;// warning if numerical IP addresses + this.ignoreLocalhost = false;// warning if localhost-URLs - } + this.prefixOnlyHrefExtensions = Web.POSSIBLE_EXTENSIONS; - /** - * @return the number of configuration items - */ - public int nrOfConfigurationItems() { - return configurationItems.size(); + this.checksToExecute = AllCheckers.CHECKER_CLASSES; } /** - * add a single configuration item, unless its value is null - * - * @param itemName - * @param itemValue + * Convenience method for simplified testing */ - public void addConfigurationItem(String itemName, Object itemValue) { - if (itemValue != null) { - configurationItems.put(itemName, itemValue); - } - + public synchronized void setSourceConfiguration(final File sourceDir, final Set sourceDocuments) { + this.sourceDir = sourceDir; + this.sourceDocuments = sourceDocuments; } /** * overwrites httpSuccessCodes configuration */ - public void overwriteHttpSuccessCodes(Collection additionalSuccessCodes) { - final Set errCodes = (Set) getConfigItemByName(Configuration.getITEM_NAME_httpErrorCodes()); - final Set warnCodes = (Set) getConfigItemByName(Configuration.getITEM_NAME_httpWarningCodes()); - final Set successCodes = (Set) getConfigItemByName(Configuration.getITEM_NAME_httpSuccessCodes()); - - additionalSuccessCodes.forEach(co -> { - successCodes.add(co); - errCodes.remove(co); - warnCodes.remove(co); - } - ); - - updateSuccessWarningErrorCodesConfiguration(errCodes, warnCodes, successCodes); + public void overrideHttpSuccessCodes(Set additionalSuccessCodes) { + if (null != additionalSuccessCodes) { + additionalSuccessCodes.forEach(co -> { + httpSuccessCodes.add(co); + httpWarningCodes.remove(co); + httpErrorCodes.remove(co); + } + ); + } else { + log.warn("Trying to override http success codes with empty set of codes"); + } } /** * overwrites httpWarningCodes configuration */ - public void overwriteHttpWarningCodes(Collection additionalWarningCodes) { - final Set errCodes = (Set) getConfigItemByName(Configuration.getITEM_NAME_httpErrorCodes()); - final Set warnCodes = (Set) getConfigItemByName(Configuration.getITEM_NAME_httpWarningCodes()); - final Set successCodes = (Set) getConfigItemByName(Configuration.getITEM_NAME_httpSuccessCodes()); - - additionalWarningCodes.forEach(co -> { - successCodes.add(co); - errCodes.remove(co); - warnCodes.remove(co); - } - ); - - updateSuccessWarningErrorCodesConfiguration(errCodes, warnCodes, successCodes); + public void overrideHttpWarningCodes(Set additionalWarningCodes) { + if (null != additionalWarningCodes) { + additionalWarningCodes.forEach(co -> { + httpSuccessCodes.remove(co); + httpWarningCodes.add(co); + httpErrorCodes.remove(co); + } + ); + } else { + log.warn("Trying to override http warning codes with empty set of codes"); + } } /** * overwrites httpErrorCodes configuration */ - public void overwriteHttpErrorCodes(Collection additionalErrorCodes) { - final Set errCodes = (Set) getConfigItemByName(Configuration.getITEM_NAME_httpErrorCodes()); - final Set warnCodes = (Set) getConfigItemByName(Configuration.getITEM_NAME_httpWarningCodes()); - final Set successCodes = (Set) getConfigItemByName(Configuration.getITEM_NAME_httpSuccessCodes()); - - additionalErrorCodes.forEach(co -> { - successCodes.add(co); - errCodes.remove(co); - warnCodes.remove(co); - } - ); - - updateSuccessWarningErrorCodesConfiguration(errCodes, warnCodes, successCodes); - } - - public void updateSuccessWarningErrorCodesConfiguration(Object errCodes, Object warnCodes, Object successCodes) { - addConfigurationItem(Configuration.getITEM_NAME_httpErrorCodes(), errCodes); - addConfigurationItem(Configuration.getITEM_NAME_httpWarningCodes(), warnCodes); - addConfigurationItem(Configuration.getITEM_NAME_httpSuccessCodes(), successCodes); - } - - /** - * overwrites prefixOnlyHrefExtensions - */ - public void overwritePrefixOnlyHrefExtensions(Collection prefixesToBeConsidered) { - addConfigurationItem(Configuration.getITEM_NAME_prefixOnlyHrefExtensions(), prefixesToBeConsidered); + public void overrideHttpErrorCodes(Set additionalErrorCodes) { + if (null != additionalErrorCodes) { + additionalErrorCodes.forEach(co -> { + httpSuccessCodes.remove(co); + httpWarningCodes.remove(co); + httpErrorCodes.add(co); + } + ); + } else { + log.warn("Trying to override http error codes with empty set of codes"); + } } /** * checks plausibility of configuration: * We need at least one html file as input, maybe several - * - * @param configuration instance - *

- * srcDocs needs to be of type {@link FileCollection} - * to be Gradle-compliant */ public Boolean isValid() throws MisconfigurationException { - // we need at least srcDir and srcDocs!! - File srcDir = (File) getConfigItemByName(Configuration.getITEM_NAME_sourceDir()); - Set srcDocs = (Set) getConfigItemByName(Configuration.getITEM_NAME_sourceDocuments()); - // cannot check if source director is null (= unspecified) - if ((srcDir == null)) { + if ((sourceDir == null)) { throw new MisconfigurationException("source directory must not be null"); } - if ((!srcDir.exists())) { - throw new MisconfigurationException("given sourceDir " + srcDir + " does not exist."); + if ((!sourceDir.exists())) { + throw new MisconfigurationException("given sourceDir " + sourceDir + " does not exist."); } // cannot check if both input params are null - if (srcDocs == null) { + if (sourceDocuments == null) { throw new MisconfigurationException("source documents must not be null"); } // empty SrcDocs - if (srcDocs.isEmpty()) { + if (sourceDocuments.isEmpty()) { throw new MisconfigurationException("source documents must not be empty"); } - Object checksToExecute = getConfigItemByName(Configuration.getITEM_NAME_checksToExecute()); - if (!(checksToExecute == null || checksToExecute instanceof Collection)) { - throw new MisconfigurationException("checks to execute have to be a non empty collection"); + if (checksToExecute == null || checksToExecute.isEmpty()) { + throw new MisconfigurationException("checks to execute have to be a non-empty list"); } @@ -310,10 +160,4 @@ public Boolean isValid() throws MisconfigurationException { // the configuration seems to be valid.. return true; } - - @Override - public String toString() { - return "Configuration{" + "configurationItems=" + configurationItems + "}"; - } - } diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/MisconfigurationException.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/MisconfigurationException.java index 583b32b3..95d8061f 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/MisconfigurationException.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/MisconfigurationException.java @@ -5,7 +5,7 @@ import java.io.File; -class MisconfigurationException extends Exception { +public class MisconfigurationException extends Exception { public MisconfigurationException(String message, File srcDir) { diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/AllCheckers.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/AllCheckers.java index 7850aacf..2d792cc8 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/AllCheckers.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/AllCheckers.java @@ -1,9 +1,9 @@ package org.aim42.htmlsanitycheck.check; import java.util.Arrays; -import java.util.LinkedHashSet; +import java.util.List; -/************************************************************************ +/* *********************************************************************** * This is free software - without ANY guarantee! * * @@ -23,14 +23,13 @@ * *********************************************************************** */ public class AllCheckers { - public static final LinkedHashSet> checkerClazzes = - new LinkedHashSet>( - Arrays.asList( - BrokenCrossReferencesChecker.class, - BrokenHttpLinksChecker.class, - DuplicateIdChecker.class, - ImageMapChecker.class, - MissingAltInImageTagsChecker.class, - MissingImageFilesChecker.class, - MissingLocalResourcesChecker.class)); + public static final List> CHECKER_CLASSES = + Arrays.asList( + BrokenCrossReferencesChecker.class, + BrokenHttpLinksChecker.class, + DuplicateIdChecker.class, + ImageMapChecker.class, + MissingAltInImageTagsChecker.class, + MissingImageFilesChecker.class, + MissingLocalResourcesChecker.class); } diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/BrokenHttpLinksChecker.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/BrokenHttpLinksChecker.java index acb0c5a8..a0731cf2 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/BrokenHttpLinksChecker.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/BrokenHttpLinksChecker.java @@ -12,7 +12,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.UnknownHostException; -import java.util.Collection; import java.util.Set; @@ -23,9 +22,9 @@ class BrokenHttpLinksChecker extends Checker { // get the (configured) statusCodes, just syntactic sugar... - private final Collection successCodes; - private final Collection warningCodes; - private final Collection errorCodes; + private final Set successCodes; + private final Set warningCodes; + private final Set errorCodes; // all href attributes with http(s) protocol, // including potential duplicates // need that to calculate "nrOfOccurrences" @@ -36,9 +35,9 @@ class BrokenHttpLinksChecker extends Checker { BrokenHttpLinksChecker(Configuration pConfig) { super(pConfig); - errorCodes = getMyConfig().getConfigItemByNameSetOfIntegers(Configuration.getITEM_NAME_httpErrorCodes()); - warningCodes = getMyConfig().getConfigItemByNameSetOfIntegers(Configuration.getITEM_NAME_httpWarningCodes()); - successCodes = getMyConfig().getConfigItemByNameSetOfIntegers(Configuration.getITEM_NAME_httpSuccessCodes()); + errorCodes = getMyConfig().getHttpErrorCodes(); + warningCodes = getMyConfig().getHttpWarningCodes(); + successCodes = getMyConfig().getHttpSuccessCodes(); } @Override @@ -81,7 +80,6 @@ private void addWarningIfNoInternetConnection() { private void checkAllHttpLinks() { // for all hrefSet check if the corresponding link is valid hrefSet.forEach(this::doubleCheckSingleHttpLink); - } /** @@ -187,7 +185,7 @@ private HttpURLConnection getNewURLConnection(URL url) throws IOException { // httpConnectionTimeout is a configuration parameter // that defaults to 5000 (msec) connection.setConnectTimeout( - (Integer) getMyConfig().getConfigItemByName(Configuration.getITEM_NAME_httpConnectionTimeout()) + getMyConfig().getHttpConnectionTimeout() ); // to avoid nasty 403 errors (forbidden), we set a referrer and user-agent @@ -203,7 +201,7 @@ private HttpURLConnection getNewURLConnection(URL url) throws IOException { // if configured, ip addresses in URLs yield warnings private void checkIfIPAddress(URL url, String href) { - if (!(Boolean) getMyConfig().getConfigItemByName(Configuration.getITEM_NAME_ignoreIPAddresses())) { + if (!getMyConfig().getIgnoreIPAddresses()) { String host = url.getHost(); if (host.matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")) { @@ -215,7 +213,7 @@ private void checkIfIPAddress(URL url, String href) { // if configured ,localhost-URLs yield warnings! private void checkIfLocalhostURL(URL url, String href) { - if (!(Boolean) getMyConfig().getConfigItemByName(Configuration.getITEM_NAME_ignoreLocalhost())) { + if (!getMyConfig().getIgnoreLocalhost()) { String host = url.getHost(); if (("localhost".equals(host)) || host.startsWith("127.0.0")) { Finding localhostWarning = new Finding("Warning: localhost urls indicates suspicious environment dependency: href=" + href); diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/Checker.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/Checker.java index 46475b59..362d91d9 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/Checker.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/Checker.java @@ -1,5 +1,7 @@ package org.aim42.htmlsanitycheck.check; +import lombok.Getter; +import lombok.Setter; import org.aim42.htmlsanitycheck.Configuration; import org.aim42.htmlsanitycheck.collect.SingleCheckResults; import org.aim42.htmlsanitycheck.html.HtmlPage; @@ -15,6 +17,8 @@ * * @author Gernot Starke */ +@Setter +@Getter public abstract class Checker { private SingleCheckResults checkingResults; private Configuration myConfig; @@ -49,25 +53,10 @@ public SingleCheckResults performCheck(final HtmlPage pageToCheck) { /** * Perform a particular kind of checks, i.e. missing-local-images-check *

- * Called by {@link #performCheck()} as part of the template method pattern. + * Called by {@link #performCheck(HtmlPage)} as part of the template method pattern. * * @return collected results of this Checker instance */ protected abstract SingleCheckResults check(final HtmlPage pageToCheck); - public SingleCheckResults getCheckingResults() { - return checkingResults; - } - - public void setCheckingResults(SingleCheckResults checkingResults) { - this.checkingResults = checkingResults; - } - - public Configuration getMyConfig() { - return myConfig; - } - - public void setMyConfig(Configuration myConfig) { - this.myConfig = myConfig; - } } diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/CheckerCreator.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/CheckerCreator.java index 2fa8b9d6..9f9b3297 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/CheckerCreator.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/CheckerCreator.java @@ -4,8 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Collection; -import java.util.Set; +import java.util.List; import java.util.stream.Collectors; /** @@ -14,11 +13,11 @@ public class CheckerCreator { private static final Logger logger = LoggerFactory.getLogger(CheckerCreator.class); - public static Set createCheckerClassesFrom(final Collection> checkerClasses, final Configuration pConfig) { + public static List createCheckerClassesFrom(final List> checkerClasses, final Configuration configuration) { return checkerClasses.stream() - .map(checkerClass -> CheckerCreator.createSingleChecker(checkerClass, pConfig)) - .collect(Collectors.toSet()); + .map(checkerClass -> CheckerCreator.createSingleChecker(checkerClass, configuration)) + .collect(Collectors.toList()); } private static boolean isCase(Class caseValue, Class switchValue) { diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/ImageMapChecker.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/ImageMapChecker.java index 3de60b03..4495fd19 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/ImageMapChecker.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/ImageMapChecker.java @@ -6,6 +6,7 @@ import org.aim42.htmlsanitycheck.html.HtmlElement; import org.aim42.htmlsanitycheck.html.HtmlPage; import org.aim42.htmlsanitycheck.tools.Web; +import org.jsoup.nodes.Element; import java.util.HashSet; import java.util.List; @@ -20,15 +21,13 @@ * 4.) every area-tag has one non-empty href attribute * 5.) every href points to valid target (broken-links check) *

- * see also: http://www.w3schools.com/tags/tag_map.asp + * see also: http://www.w3schools.com/tags/tag_map.asp **/ public class ImageMapChecker extends Checker { - private List maps; private List mapNames; private List imagesWithUsemapRefs; private List usemapRefs; private List listOfIds; - private String findingText; private HtmlPage pageToCheck; @@ -70,20 +69,22 @@ private void checkDanglingMaps() { .forEach(findingText -> getCheckingResults().addFinding(new Finding(findingText))); } + /* + * search for maps that are NOT referenced by any image-tag + */ private void checkEmptyMaps() { - mapNames.stream().map(mapName -> - pageToCheck.getAllAreasForMapName(mapName)) - .filter(areas -> !areas.isEmpty()) - .peek(a -> getCheckingResults().incNrOfChecks()) - .forEach(area -> getCheckingResults().addFinding(new Finding(findingText))); + mapNames.forEach(mapName -> { + List areas = pageToCheck.getAllAreasForMapName(mapName); + if (areas.isEmpty()) { + getCheckingResults().addFinding(new Finding(String.format("ImageMap \"%s\" has no area tags.", mapName))); + } + }); } /* check for duplicate map names */ private void checkDuplicateMapNames() { - int mapNameCount; - Set mapNameSet = new HashSet<>(mapNames); mapNameSet.stream() @@ -102,26 +103,26 @@ private void checkDuplicateMapNames() { * b.) if there are more maps named "y" -> problem */ private void checkBrokenImageMapReferences() { - imagesWithUsemapRefs.stream() + imagesWithUsemapRefs .forEach(imageTag -> checkBrokenImageMapReference(imageTag.getUsemapRef(), imageTag)); } private void checkBrokenImageMapReference(String imgMap, HtmlElement imageTag) { getCheckingResults().incNrOfChecks(); - - long mapCount = mapNames.stream().filter(it -> it == imgMap).count(); + long mapCount = mapNames.stream().filter(it -> it.equals(imgMap)).count(); if (mapCount == 0L) { // no map found, despite img-tag usemap-reference - findingText = "ImageMap \"" + imageTag.getUsemapRef() + "\" (referenced by image \"" + imageTag.getImageSrcAttribute() + "\") missing."; - getCheckingResults().addFinding(new Finding(findingText)); + getCheckingResults().addFinding( + new Finding(String.format("ImageMap \"%s\" (referenced by image \"%s\") missing.", + imageTag.getUsemapRef(), imageTag.getImageSrcAttribute()))); } } private void checkForBrokenHrefLinks() { - mapNames.forEach(n -> checkAreaHrefsForMapName(n)); + mapNames.forEach(this::checkAreaHrefsForMapName); } /* @@ -135,7 +136,7 @@ private void checkAreaHrefsForMapName(String mapName) { areaHrefs.stream() .peek(a -> getCheckingResults().incNrOfChecks()) - .filter(href -> Web.isCrossReference(href)) + .filter(Web::isCrossReference) .forEach(href -> checkLocalHref(href, mapName, areaHrefs)); } @@ -153,12 +154,12 @@ private void checkLocalHref(String href, String mapName, List areaHrefs) if (!listOfIds.contains(linkTarget)) { // we found a broken link! - findingText = "ImageMap \"" + mapName + "\" refers to missing link \"" + linkTarget + "\""; + String findingText = String.format("ImageMap \"%s\" refers to missing link \"%s\"", mapName, linkTarget); // now count occurrences - how often is it referenced - int nrOfReferences = (int) areaHrefs.stream().filter(it -> it == href).count(); + int nrOfReferences = (int) areaHrefs.stream().filter(it -> it.equals(href)).count(); if (nrOfReferences > 1) { - findingText += ", reference count: " + nrOfReferences + "."; + findingText += String.format(", reference count: %d.", nrOfReferences); } else findingText += "."; getCheckingResults().newFinding(findingText, nrOfReferences); @@ -171,7 +172,7 @@ private void readImageMapAttributesFromHtml() { imagesWithUsemapRefs = pageToCheck.getImagesWithUsemapDeclaration(); // get all ... - maps = pageToCheck.getAllImageMaps(); + pageToCheck.getAllImageMaps(); // get the names of all maps mapNames = pageToCheck.getAllMapNames(); diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/MissingImageFilesChecker.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/MissingImageFilesChecker.java index a9b711f1..8c482f25 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/MissingImageFilesChecker.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/MissingImageFilesChecker.java @@ -18,12 +18,12 @@ public class MissingImageFilesChecker extends Checker { private static final Logger logger = LoggerFactory.getLogger(MissingImageFilesChecker.class); private List images; - private final File baseDir; + final File baseDir; private File currentDir; public MissingImageFilesChecker(Configuration pConfig) { super(pConfig); - baseDir = ((File) (getMyConfig().getConfigItemByName(Configuration.getITEM_NAME_sourceDir()))); + baseDir = getMyConfig().getSourceDir(); } @Override @@ -52,7 +52,7 @@ protected SingleCheckResults check(final HtmlPage pageToCheck) { private void checkAllImages() { - images.forEach(image -> checkSingleLocalImage(image)); + images.forEach(this::checkSingleLocalImage); } @@ -63,23 +63,22 @@ private void checkSingleLocalImage(HtmlElement image) { // (that is, NO remote URL) boolean isRemoteURL = Web.isRemoteURL(imageSrcAttribute); boolean isDataURI = Web.isDataURI(imageSrcAttribute); - if (isRemoteURL) { - //do nothing. This checks for _local_ images - } else if (isDataURI) { - // bookkeeping: - getCheckingResults().incNrOfChecks(); + if (!isRemoteURL) { + if (isDataURI) { + // bookkeeping: + getCheckingResults().incNrOfChecks(); - doesDataURIContainData(imageSrcAttribute); + doesDataURIContainData(imageSrcAttribute); - } else { - //we have a simple local image + } else { + //we have a simple local image - // bookkeeping: - getCheckingResults().incNrOfChecks(); + // bookkeeping: + getCheckingResults().incNrOfChecks(); - doesImageFileExist(imageSrcAttribute); + doesImageFileExist(imageSrcAttribute); + } } - } /** @@ -90,7 +89,7 @@ private void checkSingleLocalImage(HtmlElement image) { private void doesImageFileExist(String relativePathToImageFile) { File parentDir = relativePathToImageFile.startsWith("/") ? baseDir : currentDir; - String decodedRelativePathtoImageFile = null; + String decodedRelativePathtoImageFile; try { decodedRelativePathtoImageFile = URLDecoder.decode(relativePathToImageFile,"UTF-8"); } catch (UnsupportedEncodingException e) { diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/MissingLocalResourcesChecker.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/MissingLocalResourcesChecker.java index 75ef6f08..a2c76a6c 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/MissingLocalResourcesChecker.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/MissingLocalResourcesChecker.java @@ -10,6 +10,7 @@ import java.io.File; import java.net.URI; import java.net.URISyntaxException; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -19,7 +20,9 @@ public class MissingLocalResourcesChecker extends Checker { public static final String MLRC_MESSAGE_MISSING = "missing"; public static final String MLRC_REFCOUNT = ", reference count: "; private static final Logger logger = LoggerFactory.getLogger(MissingLocalResourcesChecker.class); - private Set localResourcesSet; + // NOTE that we need, both the full list as well as the unique set of resources + // List of the local resources referenced in anchor tags + private List localResourcesList; /** * The base directory to resolve absolute paths. */ @@ -29,14 +32,10 @@ public class MissingLocalResourcesChecker extends Checker { * relative paths. */ private File currentDir; - /** - * True to require files to be referenced and not directories. Useful if the web server doesn't - * support a default directory, such as Amazon S3. - */ - private final boolean requireFiles = false; + public MissingLocalResourcesChecker(Configuration pConfig) { super(pConfig); - baseDir = ((File) (pConfig.getConfigItemByName(Configuration.getITEM_NAME_sourceDir()))); + baseDir = pConfig.getSourceDir(); } @Override @@ -52,9 +51,12 @@ protected SingleCheckResults check(final HtmlPage pageToCheck) { List allHrefs = pageToCheck.getAllHrefStrings(); // now filter out all local resources + localResourcesList = allHrefs.stream().filter(Web::isLocalResource).collect(Collectors.toList()); // now filter out all local resources - localResourcesSet = allHrefs.stream().filter(Web::isLocalResource).collect(Collectors.toSet()); + // unique local references - each one is unique + // created from the List of all by toSet() method + Set localResourcesSet = new HashSet<>(localResourcesList); logger.debug("local resources set: " + localResourcesSet); @@ -71,7 +73,7 @@ protected SingleCheckResults check(final HtmlPage pageToCheck) { private void checkAllLocalResources(Set localResources) { - localResources.forEach(localResource -> checkSingleLocalResource(localResource)); + localResources.forEach(this::checkSingleLocalResource); } private void checkSingleLocalResource(String localResource) { @@ -83,7 +85,7 @@ private void checkSingleLocalResource(String localResource) { getCheckingResults().incNrOfChecks(); // we need to strip the localResource of #anchor-parts - String localResourcePath = null; + String localResourcePath; try { localResourcePath = new URI(localResource).getPath(); } catch (URISyntaxException e) { @@ -113,9 +115,11 @@ private void handleNonexistingLocalResource(final String nonExistingLocalResourc String findingText = MLRC_MESSAGE_PREFIX + " \"" + nonExistingLocalResource + "\" " + MLRC_MESSAGE_MISSING; // how often is localResource referenced? - int nrOfOccurrences = (int) localResourcesSet.stream().filter(et -> et.equals(nonExistingLocalResource)).count(); + int nrOfOccurrences = (int) localResourcesList.stream().filter(et -> et.equals(nonExistingLocalResource)).count(); - if (nrOfOccurrences > 1) findingText += MLRC_REFCOUNT + nrOfOccurrences; + if (nrOfOccurrences > 1) { + findingText += MLRC_REFCOUNT + nrOfOccurrences; + } // add Finding to our current checking results, increment nrOfFindings by nrOfOccurrences getCheckingResults().newFinding(findingText, nrOfOccurrences); diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/Finding.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/Finding.java index 758da77c..7f470181 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/Finding.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/Finding.java @@ -2,9 +2,11 @@ package org.aim42.htmlsanitycheck.collect; +import lombok.Getter; +import lombok.Setter; + import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; /** * A single "finding" from any check, i.e.: @@ -14,9 +16,12 @@ */ public class Finding { + @Getter String whatIsTheProblem; // i.e. which image is missing, which link/anchor is undefined + @Getter int nrOfOccurrences;// how often does this specific finding occur in the checked-page // suggestions are ordered: getAt(0) yields the best, getAt(1) the second and so forth + @Setter List suggestions; public Finding() { @@ -30,14 +35,14 @@ public Finding() { * @param whatIsTheProblem An explanation of what went wrong (i.e. name of missing file) */ public Finding(String whatIsTheProblem) { - this(whatIsTheProblem, 1, new ArrayList(3)); + this(whatIsTheProblem, 1, new ArrayList<>(3)); } /** * finding with explanation and several occurences */ public Finding(String whatIsTheProblem, int nrOfOccurrences) { - this(whatIsTheProblem, nrOfOccurrences, new ArrayList(3)); + this(whatIsTheProblem, nrOfOccurrences, new ArrayList<>(3)); } @@ -47,7 +52,7 @@ public Finding(String whatIsTheProblem, int nrOfOccurrences) { * * @param whatIsTheProblem An explanation of what went wrong (i.e. name of missing file) */ - public Finding(String whatIsTheProblem, int nrOfOccurrences, ArrayList suggestions) { + public Finding(String whatIsTheProblem, int nrOfOccurrences, List suggestions) { this.whatIsTheProblem = whatIsTheProblem; this.nrOfOccurrences = nrOfOccurrences; this.suggestions = suggestions; @@ -60,40 +65,14 @@ public Finding(String whatIsTheProblem, int nrOfOccurrences, ArrayList s * @param whatIsTheProblem explanation what went wrong * @param suggestions what could have been meant */ - public Finding(String whatIsTheProblem, ArrayList suggestions) { + public Finding(String whatIsTheProblem, List suggestions) { this(whatIsTheProblem, 1, suggestions); } - public String getWhatIsTheProblem() { - return whatIsTheProblem; - } - - public int getNrOfOccurrences() { - return nrOfOccurrences; - } - - public void setSuggestions(List suggestions) { - this.suggestions = suggestions; - } - - /** - * add a single suggestion to the list of suggestions - * - * @param suggestion - */ - public void addSingleSuggestion(String suggestion) { - suggestions.add(suggestion); - } - - - public void setNrOfOccurences(int nrOfOccurences) { - this.nrOfOccurrences = nrOfOccurrences; - } - @Override public String toString() { - String refCount = (nrOfOccurrences > 1) ? " (reference count: $nrOfOccurrences)" : ""; - String suggestionStr = (suggestions.size() > 0) ? "\n (Suggestions: " + suggestions.stream().collect(Collectors.joining(",")) + ")" : ""; + String refCount = (nrOfOccurrences > 1) ? String.format(" (reference count: %d)", nrOfOccurrences) : ""; + String suggestionStr = (!suggestions.isEmpty()) ? "\n (Suggestions: " + String.join(",", suggestions) + ")" : ""; return whatIsTheProblem + refCount + (suggestionStr.isEmpty() ? "" : suggestionStr); } diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/PerRunResults.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/PerRunResults.java index 313f227b..e210a9a6 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/PerRunResults.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/PerRunResults.java @@ -1,6 +1,8 @@ package org.aim42.htmlsanitycheck.collect; import java.util.ArrayList; +import java.util.List; +import java.util.Objects; /** * Collects checking results of 1..n html files which are checked together in one "run". @@ -13,8 +15,7 @@ public class PerRunResults implements RunResults { // magic number - also used in tests private final static Long TIMER_STILL_RUNNING = 42L; // unused images is the only check concerning all pages... - SingleCheckResults unusedImagesResultsCollector; - private final ArrayList resultsForAllPages; + private final List resultsForAllPages; // checking time is important - therefore we maintain a timer private final Long startedCheckingTimeMillis; private Long finishedCheckingTimeMillis; @@ -30,7 +31,7 @@ public PerRunResults() { this.startedCheckingTimeMillis = System.currentTimeMillis(); this.finishedCheckingTimeMillis = TIMER_STILL_RUNNING; - this.resultsForAllPages = new ArrayList(); + this.resultsForAllPages = new ArrayList<>(); } @@ -38,7 +39,7 @@ public PerRunResults() { * return the List of results for the pages */ @Override - public ArrayList getResultsForAllPages() { + public List getResultsForAllPages() { return resultsForAllPages; } @@ -55,12 +56,12 @@ public void stopTimer() { */ @Override public Long checkingTookHowManyMillis() { - Long itTookSoLong; - if (finishedCheckingTimeMillis == TIMER_STILL_RUNNING) + long itTookSoLong; + if (Objects.equals(finishedCheckingTimeMillis, TIMER_STILL_RUNNING)) { itTookSoLong = ILLEGAL_TIMER; // if read upside down: "Sie Esel" - else + } else { itTookSoLong = finishedCheckingTimeMillis - startedCheckingTimeMillis; - + } return itTookSoLong; } @@ -91,8 +92,8 @@ public int nrOfPagesChecked() { public int nrOfChecksPerformedOnAllPages() { return resultsForAllPages.stream() - .map(singlePageResults -> singlePageResults.nrOfItemsCheckedOnPage()) - .reduce((a, b) -> a + b).orElseGet(() -> 0); + .map(SinglePageResults::nrOfItemsCheckedOnPage) + .reduce(Integer::sum).orElse(0); } @@ -104,13 +105,13 @@ public int nrOfChecksPerformedOnAllPages() { public int nrOfFindingsOnAllPages() { return resultsForAllPages.stream() - .map(singlePageResults -> singlePageResults.nrOfFindingsOnPage()) - .reduce((a, b) -> a + b).orElseGet(() -> 0); + .map(SinglePageResults::nrOfFindingsOnPage) + .reduce(Integer::sum).orElse(0); } } -/************************************************************************ +/* *********************************************************************** * This is free software - without ANY guarantee! * * diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/SingleCheckResults.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/SingleCheckResults.java index 8cb4bd49..7cf8709d 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/SingleCheckResults.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/SingleCheckResults.java @@ -2,6 +2,9 @@ package org.aim42.htmlsanitycheck.collect; +import lombok.Getter; +import lombok.Setter; + import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -16,13 +19,24 @@ public class SingleCheckResults implements CheckResults { // the actual findings - public ArrayList findings; + public List findings; + @Setter + @Getter String whatIsChecked; // i.e. "Missing Local Images Check" // source-whatIsTheProblem is checked against target-whatIsTheProblem + @Setter + @Getter String sourceItemName; // i.e. image-src-attribute, anchor/link - String targetItemName; // i.e. local-image-file, id/bookmark + @Setter + @Getter + private String targetItemName; // i.e. local-image-file, id/bookmark + @Setter + @Getter String generalRemark; // i.e. "Internet not available" + @Getter int nrOfItemsChecked; + // nrOfIssues can be larger than findings.size(), + // if some findings occur more than once private int nrOfIssues; /** @@ -35,47 +49,10 @@ public SingleCheckResults() { this.nrOfItemsChecked = 0; this.nrOfIssues = 0; - this.findings = new ArrayList(); + this.findings = new ArrayList<>(); this.generalRemark = ""; } - public String getWhatIsChecked() { - return whatIsChecked; - } - - public void setWhatIsChecked(String whatIsChecked) { - this.whatIsChecked = whatIsChecked; - } - - public String getSourceItemName() { - return sourceItemName; - } - - public void setSourceItemName(String sourceItemName) { - this.sourceItemName = sourceItemName; - } - - public String getTargetItemName() { - return targetItemName; - } - - public void setTargetItemName(String targetItemName) { - this.targetItemName = targetItemName; - } - - public String getGeneralRemark() { - return generalRemark; - } - // nrOfIssues can be larger than findings.size(), - // if some findings occur more than once - - public void setGeneralRemark(String generalRemark) { - this.generalRemark = generalRemark; - } - - public int getNrOfItemsChecked() { - return nrOfItemsChecked; - } /** * add a single finding to the collection, @@ -98,13 +75,15 @@ public void newFinding(String message, int nrOfOccurrences) { /** - * add a single finding to the collection of Finding instances + * Add a single finding to the collection of Finding instances * - * @param singleFinding + * @param singleFinding the finding to be added */ public void addFinding(Finding singleFinding) { - findings.add(singleFinding); - incNrOfIssues(); + if (null != singleFinding) { + findings.add(singleFinding); + incNrOfIssues(); + } } /** @@ -122,10 +101,6 @@ public void incNrOfChecks() { nrOfItemsChecked += 1; } - public void addNrOfChecks(int nrOfChecksToAdd) { - nrOfItemsChecked += nrOfChecksToAdd; - } - public void setNrOfChecks(int nrOfChecks) { nrOfItemsChecked = nrOfChecks; } @@ -152,7 +127,7 @@ public String description() { @Override - public ArrayList getFindings() { + public List getFindings() { return findings; } @@ -161,8 +136,7 @@ public ArrayList getFindings() { * (used to simplify testing) */ public List getFindingMessages() { - return findings.stream().map(finding -> finding.getWhatIsTheProblem()).collect(Collectors.toList()); - + return findings.stream().map(Finding::getWhatIsTheProblem).collect(Collectors.toList()); } @@ -176,13 +150,9 @@ public int nrOfProblems() { @Override public String toString() { - int nrOfProblems = nrOfProblems(); - return "Checking results for $whatIsChecked" + '\n' + - " $nrOfItemsChecked $sourceItemName checked," + '\n' + - " $nrOfProblems finding(s)" + '\n' + - findings.stream().map(it -> it.toString()).collect(Collectors.joining("\n")); - - + return String.format ("Checking results for %s\n %d '%s' items checked,\n %d finding(s):\n %s", + whatIsChecked, nrOfItemsChecked, sourceItemName, nrOfIssues, + findings.stream().map(Finding::toString).collect(Collectors.joining("\n "))); } diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/html/HtmlPage.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/html/HtmlPage.java index 3b4147b8..43993818 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/html/HtmlPage.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/html/HtmlPage.java @@ -1,16 +1,19 @@ package org.aim42.htmlsanitycheck.html; +import lombok.Getter; import org.aim42.htmlsanitycheck.tools.Web; import org.jsoup.Jsoup; +import org.jsoup.nodes.Attribute; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Set; -import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -21,27 +24,26 @@ * convenience methods to access anchor and image links * from html. *

- * Relies on http://jsoup.org parser + * Relies on jsoup parser */ public class HtmlPage { - /** - * Pattern to check for HTTP/S scheme, includes the - * scheme separator (colon). - */ - private static final Pattern HTTP_SCHEME_PATTERN = Pattern.compile("(?i)^https?:"); - // jsoup Document private final Document document; /** * The HTML file. + * -- GETTER -- + * Gets the file of the HTML page. + * + * @return the file, or null if the HTML is not from a file. + */ + @Getter private File file; /** * @param text html as text (string) - * @return an HtmlPage */ public HtmlPage(String text) { // Jsoup promises to parse without exception - @@ -51,8 +53,7 @@ public HtmlPage(String text) { } /** - * @param file - * @return an HtmlPage + * @param file the HTML file */ public HtmlPage(File file) throws IOException { assert file.exists(); @@ -63,22 +64,13 @@ public HtmlPage(File file) throws IOException { /** * invokes the parser for the html page * - * @param input file + * @param fileToCheck the HTML file */ public static HtmlPage parseHtml(File fileToCheck) throws IOException { assert fileToCheck.exists(); return new HtmlPage(fileToCheck); } - /** - * Gets the file of the HTML page. - * - * @return the file, or null if the HTML is not from a file. - */ - public File getFile() { - return file; - } - /** * get document meta info (e.g. filename, title, size etc.) */ @@ -90,18 +82,10 @@ public String getDocumentTitle() { return document.title(); } - public String getDocumentURL() { - return document.nodeName(); - } - - public String getDocument() { - return document.toString(); - } - /** - * builds a list of all imageMaps + * Builds a list of all imageMaps * - * @return ArrayList of imageMaps + * @return List of imageMaps */ public final List getAllImageMaps() { return document.select("map").stream() @@ -130,7 +114,7 @@ public List getAllUsemapRefs() { /** * builds a list from all '' tags * - * @return immutable ArrayList + * @return immutable List */ public final List getAllImageTags() { return document.getElementsByTag("img").stream() @@ -153,7 +137,11 @@ public final List getAllImageTagsWithNonEmptyAltAttribute() { * the alt-tag is missing or empty (""). */ public final List getAllImageTagsWithMissingAltAttribute() { - return document.select("img[alt~=(\\S)]").stream() + return document.select("img").stream() + .filter(element -> { + Attribute alt = element.attribute("alt"); + return alt == null || alt.getValue().isEmpty(); + }) .map(HtmlElement::new) .collect(Collectors.toList()); } @@ -161,7 +149,7 @@ public final List getAllImageTagsWithMissingAltAttribute() { /** * builds a list of all ' tags * - * @return ArrayList of all hrefs, including the "#" + * @return List of all hrefs, including the "#" */ public List getAllAnchorHrefs() { return document.getElementsByAttribute("href").stream() @@ -172,7 +160,7 @@ public List getAllAnchorHrefs() { /** * builds a list of all 'id="XYZ"' attributes * - * @return ArrayList of all hrefs + * @return List of all hrefs */ public final List getAllIds() { return document.getElementsByAttribute("id").stream() @@ -181,11 +169,11 @@ public final List getAllIds() { } /** - * @return ArrayList < String > of all href-attributes + * @return List < String > of all href-attributes *

* common pitfalls with hrefs: * - local hrefs start with # (like "#appendix") - * - remote hrefs should be valid URLs (like "https://google.com") + * - remote hrefs should be valid URLs (like "https://google.com") * - remote hrefs might start with other than http (e.g. https, mailto, telnet, ssh) * - hrefs might start with file:// * - href might be empty string (nobody knows wtf this is good for, but html parsers usually accept it) @@ -226,13 +214,19 @@ public List getImagesWithUsemapDeclaration() { * for all maps are combined into one. * * @param mapName name of the map - * @return + * @return list of all contained areas */ - public List getAllAreasForMapName(String mapName) { - return document.select("map[name=" + mapName + "]").stream() - .map(m -> m.children().select("area")) - .collect(Collectors.toList()); - + public List getAllAreasForMapName(String mapName) { + List result = new ArrayList<>(); + document.select("map[name=" + mapName + "]") + .forEach(m -> { + List areas = Collections.singletonList(m.children().select("area")); + if (!areas.isEmpty()) { + result.addAll(areas); + } + } + ); + return result.stream().flatMap(List::stream).collect(Collectors.toList()); } @@ -243,7 +237,7 @@ public List getAllHrefsForMapName(String mapName) { } /** - * getAllIdStrings return ArrayList of all id="xyz" definitions + * getAllIdStrings return List of all id="xyz" definitions */ public List getAllIdStrings() { diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/report/CreateLinkUtil.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/report/CreateLinkUtil.java index 7934ec47..20720120 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/report/CreateLinkUtil.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/report/CreateLinkUtil.java @@ -6,12 +6,10 @@ * to "XdirXonefileXhtml" or similar. */ public class CreateLinkUtil { - public static String convertToLink(String stringWithNonWordChars) { - - // \W is regex for all non-word characters - String regex = "\\W "; + // \W is regex for all non-word characters + static final String regex = "[\\W ]"; + public static String convertToLink(String stringWithNonWordChars) { return stringWithNonWordChars.replaceAll(regex, "X"); } - } diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/report/Reporter.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/report/Reporter.java index 0d006224..bcfca576 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/report/Reporter.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/report/Reporter.java @@ -5,9 +5,7 @@ import org.aim42.htmlsanitycheck.collect.SingleCheckResults; import org.aim42.htmlsanitycheck.collect.SinglePageResults; - import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.List; @@ -22,7 +20,7 @@ public abstract class Reporter { * create the reporter */ public Reporter() { - this.createdOnDate = new SimpleDateFormat("dd. MMMM YYYY, HH:mm").format(new Date()); + this.createdOnDate = new SimpleDateFormat("dd. MMMM yyyy, HH:mm").format(new Date()); this.createdByHSCVersion = ProductVersion.getVersion(); } @@ -30,7 +28,7 @@ public Reporter() { /** * Usually a Reporter instance shall be constructed with its appropriate * - * @param runResults + * @param runResults the results for the report * @see PerRunResults, as the latter contains all findings. */ public Reporter(PerRunResults runResults) { @@ -76,8 +74,8 @@ private void reportAllPages() { protected void reportPageDetails(SinglePageResults pageResults) { for (SingleCheckResults resultForOneCheck : pageResults.singleCheckResults) { - reportSingleCheckSummary((SingleCheckResults) resultForOneCheck); - reportSingleCheckDetails((SingleCheckResults) resultForOneCheck); + reportSingleCheckSummary(resultForOneCheck); + reportSingleCheckDetails(resultForOneCheck); } } @@ -112,7 +110,7 @@ protected void closeReport() { // default: do nothing } - protected ArrayList pageResults; + protected List pageResults; protected PerRunResults runResults; protected final String createdOnDate; protected final String createdByHSCVersion; diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/suggest/Suggester.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/suggest/Suggester.java index 2485111b..c564ae90 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/suggest/Suggester.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/suggest/Suggester.java @@ -5,7 +5,6 @@ import net.ricecode.similarity.StringSimilarityService; import net.ricecode.similarity.StringSimilarityServiceImpl; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -26,7 +25,7 @@ public class Suggester { * @param options list of available options where the suggestion is taken from * @return a suggested alternative for target from the options */ - static String determineSingleSuggestion(String target, ArrayList options) { + static String determineSingleSuggestion(String target, List options) { service = new StringSimilarityServiceImpl(new JaroWinklerStrategy()); @@ -40,7 +39,7 @@ static String determineSingleSuggestion(String target, ArrayList options * @param target string that is not contained in options, similarity-compared to every entry in options * @param options list of available options where suggestions are taken from * @param n number of suggestions to return. Should better be lower than options.size() - * @return ArrayList of suggestions + * @return List of suggestions */ public static List determineNSuggestions(String target, List options, int n) { service = new StringSimilarityServiceImpl(new JaroWinklerStrategy()); @@ -54,7 +53,7 @@ public static List determineNSuggestions(String target, List opt } } -/************************************************************************ +/* *********************************************************************** * This is free software - without ANY guarantee! *

*

diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/tools/Web.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/tools/Web.java index 6c8d8709..15e1c341 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/tools/Web.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/tools/Web.java @@ -1,7 +1,14 @@ package org.aim42.htmlsanitycheck.tools; -import java.io.IOException; -import java.net.*; +import org.apache.commons.validator.routines.InetAddressValidator; + +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; @@ -17,32 +24,30 @@ public class Web { // these are regarded as "Success" when checking // http(s) links - public static final Set HTTP_SUCCESS_CODES = initErrorCodes(200, 208, 226, 226); + public static final Set HTTP_SUCCESS_CODES = initHttpReturnCodes(200, 208, 226, 226); - public static final Set HTTP_WARNING_CODES = initErrorCodes(100, 102, 300, 308); + public static final Set HTTP_WARNING_CODES = initHttpReturnCodes(100, 102, 300, 308); - public static final Set HTTP_ERROR_CODES = initErrorCodes(400, 451, 500, 511); + public static final Set HTTP_ERROR_CODES = initHttpReturnCodes(400, 451, 500, 511); - public static final Set HTTP_REDIRECT_CODES = initErrorCodes(301, 303, 307, 308); + public static final Set HTTP_REDIRECT_CODES = initHttpReturnCodes(301, 303, 307, 308); public static final Set POSSIBLE_EXTENSIONS = initExtentions(); - static private final Pattern httpPatter = Pattern.compile("^https?"); + static private final Pattern httpPattern = Pattern.compile("^https?:"); static private final Pattern mailPattern = Pattern.compile("^(?i)(mailto):.*$"); - private static final Pattern ipPattern = Pattern.compile("\"\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\""); - private static final Pattern dataImagePattern = Pattern.compile("^(?i)(data:image).*$"); private static final Pattern remoteImagePattern = Pattern.compile("^(?i)(https?|ftp|telnet|ssh|ssl|gopher|localhost)://.*"); private static final Pattern linkPattern = Pattern.compile("^//.*$"); - private static Set initErrorCodes(int alow, int ahigh, int blow, int high) { + private static Set initHttpReturnCodes(int alow, int ahigh, int blow, int high) { Set result = IntStream.rangeClosed(alow, ahigh).collect(HashSet::new, Set::add, Set::addAll); result.addAll(IntStream.rangeClosed(blow, high).collect(HashSet::new, Set::add, Set::addAll)); - return result; + return Collections.unmodifiableSet(result); } private static Set initExtentions() { @@ -79,51 +84,26 @@ static public boolean isInternetConnectionAvailable() { } static public boolean isWebUrl(String possibleUrl) { - return httpPatter.matcher(possibleUrl).find(); - } - - public static boolean isLocahost(URL url) { - String host = url.getHost(); - return host.equals("localhost") || host.startsWith("127.0.0"); - } - - public static boolean isIP(URL url) { - return isIP(url.getHost()); + return httpPattern.matcher(possibleUrl).find(); } - public static boolean isIP(String url) { - return ipPattern.matcher(url).find(); + public static boolean isIP(String ip) { + return InetAddressValidator.getInstance().isValid(ip); } - public static HttpURLConnection getNewURLConnection(URL url) throws IOException { - - TrustAllCertificates.install(); - - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("HEAD"); - - // httpConnectionTimeout defaults to 5000 (msec) - connection.setConnectTimeout(5000); - - // to avoid nasty 403 errors (forbidden), we set a referrer and user-agent - // - connection.setRequestProperty("Referer", "https://aim42.org"); - connection.setRequestProperty("User-Agent", "Mozilla/5.0 (X11; Linux i686; rv:10.0) Gecko/20100101 Firefox/10.0"); - - // TODO followRedirects should be a configuration parameter - // that defaults to false - - return connection; + public static boolean startsWithIP(String url) { + int slashPos = url.indexOf('/'); + if (slashPos > 0) { + String host = url.substring(0, slashPos); + return isIP(host); + } + return false; } public static boolean isSuccessCode(int responseCode) { return HTTP_SUCCESS_CODES.contains(responseCode); } - public static boolean isRedirectCode(int responseCode) { - return HTTP_REDIRECT_CODES.contains(responseCode); - } - public static boolean isWarningCode(int responseCode) { return HTTP_WARNING_CODES.contains(responseCode); } @@ -137,12 +117,13 @@ public static boolean isErrorCode(int responseCode) { * Checks if this String represents a remote URL * (startsWith http, https, ftp, telnet...) * - * @param link + * @param imgSrc the image URL to be checked */ public static boolean isRemoteURL(String imgSrc) { return remoteImagePattern.matcher(imgSrc).find() || mailPattern.matcher(imgSrc).find() - || isIP(imgSrc); + || isIP(imgSrc) + || startsWithIP(imgSrc); } @@ -150,7 +131,7 @@ public static boolean isRemoteURL(String imgSrc) { * Checks if this String represents a data-image-URI * (startsWith "data:image" * - * @param s + * @param imgSrc the image URL to be checked */ public static boolean isDataURI(String imgSrc) { return dataImagePattern.matcher(imgSrc).find(); @@ -161,7 +142,7 @@ public static boolean isDataURI(String imgSrc) { * Checks if this String represents a cross-reference, * that is an intra-document link * - * @param xref + * @param xref the cross reference to be checked */ public static boolean isCrossReference(String xref) { @@ -171,20 +152,17 @@ public static boolean isCrossReference(String xref) { } + private static final Pattern ILLEGAL_CHARS_REGEX = Pattern.compile("[ *$]"); /** * helper to identify invalid characters in link * - * @param aLink + * @param aLink the link to be checked */ public static boolean containsInvalidChars(String aLink) { // TODO finding illegal chars with a regex is overly simple, // as different chars are allowed in different parts of an URI... // simple solution works for htmlSanityCheck - - - Pattern illegalCharsRegex = Pattern.compile(" |\\*|\\$"); - - return illegalCharsRegex.matcher(aLink).find(); + return ILLEGAL_CHARS_REGEX.matcher(aLink).find(); } /** @@ -202,11 +180,9 @@ public static boolean isLocalResource(String link) { || (link.isEmpty()) || isCrossReference(link) // "#link" or similar || isRemoteURL(link) // "mailto:", "http" etc - - ) + ) { return false; - - else { + } else { URI aUri; try { aUri = new URI(link); @@ -225,8 +201,8 @@ public static boolean isLocalResource(String link) { } - /* - ** helper to identify "file scheme" + /** + * helper to identify "file scheme" */ private static Boolean isLinkToFile(URI aUri) { if (aUri == null || aUri.getScheme() == null) { @@ -240,13 +216,13 @@ private static Boolean isLinkToFile(URI aUri) { /** * Checks if this String represents a valid URI/URL * - * @param link + * @param link the URL to be checked * @return boolean */ public static boolean isValidURL(String link) { // TODO: refactor this code to use org.apache.commons.validator.routines.* - boolean isValid = false; + boolean isValid; if (isCrossReference(link)) { return true; @@ -269,7 +245,7 @@ public static boolean isValidURL(String link) { } -/************************************************************************ +/* *********************************************************************** * This is free software - without ANY guarantee! * * diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/AllChecksRunnerTest.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/AllChecksRunnerTest.groovy index 8e710d91..0d30095e 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/AllChecksRunnerTest.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/AllChecksRunnerTest.groovy @@ -16,15 +16,13 @@ class AllChecksRunnerTest { private Configuration myConfig = new Configuration() @Test - public void testSingleCorrectHTMLFile() { + void testSingleCorrectHTMLFile() { String HTML = """$HTML_HEADhsc""" // create file with proper html content tmpFile = File.createTempFile("testfile", ".html") <Faulty Dragon

dummy-heading-1

duplicate id

@@ -62,14 +60,13 @@ class AllChecksRunnerTest { // create file tmpFile = File.createTempFile("testfile", ".html") << HTML - myConfig.addConfigurationItem( Configuration.ITEM_NAME_sourceDocuments, [tmpFile]) - myConfig.addConfigurationItem( Configuration.ITEM_NAME_sourceDir, tmpFile.parentFile) + myConfig.setSourceConfiguration(tmpFile.parentFile, [tmpFile] as Set) allChecksRunner = new AllChecksRunner( myConfig ) SinglePageResults pageResults = allChecksRunner.performChecksForOneFile( tmpFile ) - int expected = AllCheckers.checkerClazzes.size() + int expected = AllCheckers.CHECKER_CLASSES.size() TestCase.assertEquals("expected $expected kinds of checks", expected, pageResults.singleCheckResults.size()) TestCase.assertEquals("expected 2 findings", 2, pageResults.nrOfFindingsOnPage()) @@ -77,14 +74,17 @@ class AllChecksRunnerTest { } @Test - public void testUsingSubsetOfChecks() { + void testUsingSubsetOfChecks() { tmpFile = File.createTempFile("testfile", ".html") << """$HTML_HEADhsc""" - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDocuments, [tmpFile]) - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDir, tmpFile.parentFile) - myConfig.addConfigurationItem(Configuration.ITEM_NAME_checksToExecute, [AllCheckers.checkerClazzes.first()]) + Configuration config = Configuration + .builder() + .sourceDir(tmpFile.parentFile) + .sourceDocuments([tmpFile] as Set) + .checksToExecute([AllCheckers.CHECKER_CLASSES.first()]) + .build() - allChecksRunner = new AllChecksRunner(myConfig) + allChecksRunner = new AllChecksRunner(config) SinglePageResults pageResults = allChecksRunner.performChecksForOneFile(tmpFile) TestCase.assertEquals(1, pageResults.singleCheckResults.size()) diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/ConfigurationSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/ConfigurationSpec.groovy index 49703ad0..7296d5bb 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/ConfigurationSpec.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/ConfigurationSpec.groovy @@ -1,5 +1,6 @@ package org.aim42.htmlsanitycheck +import org.aim42.htmlsanitycheck.check.Checker import spock.lang.Specification import spock.lang.Unroll @@ -8,14 +9,10 @@ import spock.lang.Unroll class ConfigurationSpec extends Specification { - def CI_FileCheck_Name = "fileToCheck" - def CI_FileCheck_Value = "index.html" - private final static HTML_HEADER = """ """ private File tempDir private File htmlFile - private File nonHtmlFile private Configuration myConfig @@ -23,121 +20,64 @@ class ConfigurationSpec extends Specification { myConfig = new Configuration() } - /** - * The very basic SmokeTest for configuration items - * @return - */ - def "can add and retrieve single config item"() { - - when: "we add a single configuration item" - myConfig.addConfigurationItem(CI_FileCheck_Name, CI_FileCheck_Value) - - then: "we can retrieve this item" - myConfig.getConfigItemByName(CI_FileCheck_Name) == CI_FileCheck_Value - - } - - def "checks if item is already present in configuration"() { - when: "we configure a single item" - myConfig.addConfigurationItem(CI_FileCheck_Name, "test") - - then: "a check finds this item" - myConfig.checkIfItemPresent(CI_FileCheck_Name) == true - } - - - def "configuration item can be overwritten"() { - String oneITEM = "oneITEM" - - given: "an (int) item is configured" - myConfig.addConfigurationItem(oneITEM, 10) - - when: "this item is configured again!" - myConfig.addConfigurationItem(oneITEM, 42) - - then: "only the last value is contained in Configuration" - myConfig.getConfigItemByName(oneITEM) == 42 - - } - - - def "not configured item yields null result"() { - given: " a single entry configuration" - myConfig.addConfigurationItem(CI_FileCheck_Name, CI_FileCheck_Value) - - expect: "when a different config item is requested, null is returned" - myConfig.getConfigItemByName("NonExistingItem") == null - } - - @Unroll - def "can add and retrieve item #itemName of type #itemValue.getClass()"() { - when: "we add #itemName" - myConfig.addConfigurationItem(itemName, itemValue) + def "can overwrite http success codes"() { - and: "we retrieve that value from our configuration" - def value = myConfig.getConfigItemByName(itemName) + given: "configuration where 503 is success instead of error" + int newSuccessCode = 503 + Set httpSuccessCodes = [newSuccessCode] + when: "we overwrite the standard Configuration with this value" + myConfig.overrideHttpSuccessCodes(httpSuccessCodes) - then: "we retrieve the correct value" - value == itemValue + then: "503 IS now contained in successCodes" + myConfig.getHttpSuccessCodes().contains(newSuccessCode) - and: "that value has the correct type" - value.getClass() == itemValue.getClass() + and: "503 is NOT contained in errorCodes" + !myConfig.getHttpErrorCodes().contains(newSuccessCode) - where: + and: "503 is NOT contained in warningCodes" + !myConfig.getHttpWarningCodes().contains(newSuccessCode) - itemName | itemValue - "CI_FileName" | "index.html" - "CI_NumberSmall" | 42 - "CI_Number2Bigger" | 80.000 - "CI_Dir" | "/report/htmlchecks/" - "CI_Bool" | false - "CI_Map" | [Warning: [300, 301, 305], Error: [400, 404]] - "CI_List" | ["https://arc42.org", "https://aim42.org"] } + def "can overwrite http warning codes"() { - def "can overwrite http success codes"() { - - given: "configuration where 503 is success instead of error" - int newSuccessCode = 503 - ArrayList httpSuccessCodes = [newSuccessCode] + given: "configuration where 201 is warning instead of success" + int newWarningCode = 201 + Set httpWarningCodes = [newWarningCode] when: "we overwrite the standard Configuration with this value" - myConfig.overwriteHttpSuccessCodes( httpSuccessCodes ) + myConfig.overrideHttpWarningCodes(httpWarningCodes) - then: "503 IS now contained in successCodes" - myConfig.getConfigItemByName(Configuration.ITEM_NAME_httpSuccessCodes).contains(newSuccessCode) + then: "201 IS now contained in warningCodes" + myConfig.getHttpWarningCodes().contains(newWarningCode) - and: "503 is NOT contained in errorCodes" - !myConfig.getConfigItemByName(Configuration.ITEM_NAME_httpErrorCodes).contains(newSuccessCode) + and: "201 is NOT contained in errorCodes" + !myConfig.getHttpErrorCodes().contains(newWarningCode) - and: "503 is NOT contained in warningCodes" - !myConfig.getConfigItemByName(Configuration.ITEM_NAME_httpWarningCodes).contains(newSuccessCode) + and: "201 is NOT contained in successCodes" + !myConfig.getHttpSuccessCodes().contains(newWarningCode) } - def "ignore null values in configuration"() { - final String itemName = "NonExistingItem" + def "can overwrite http error codes"() { - when: "we try to add a null value to a config item" - myConfig.addConfigurationItem(itemName, null) + given: "configuration where 403 is error instead of warning" + int newErrorCode = 403 + Set httpErrorCodes = [newErrorCode] - then: "this value is NOT added to configuration" - myConfig.checkIfItemPresent( itemName ) == false - } + when: "we overwrite the standard Configuration with this value" + myConfig.overrideHttpErrorCodes(httpErrorCodes) - def "avoid overriding config values with null"() { - final String itemName = "SomeItem" + then: "403 IS now contained in errorCodes" + myConfig.getHttpErrorCodes().contains(newErrorCode) - given: "someItem with value 42" - myConfig.addConfigurationItem(itemName, 42) + and: "403 is NOT contained in successCodes" + !myConfig.getHttpSuccessCodes().contains(newErrorCode) - when: "we try to overwrite itemName with null value" - myConfig.addConfigurationItem(itemName, null) + and: "403 is NOT contained in warningCodes" + !myConfig.getHttpWarningCodes().contains(newErrorCode) - then: "the result is still 42" - myConfig.getConfigItemByName(itemName) == 42 } def "configuring a single html file is ok"() { @@ -147,7 +87,7 @@ class ConfigurationSpec extends Specification { htmlFile = new File(tempDir, "a.html") << HTML_HEADER when: "we create a configuration with this single file" - myConfig.addSourceFileConfiguration(tempDir, [htmlFile]) + myConfig.setSourceConfiguration(tempDir, [htmlFile] as Set) myConfig.isValid() @@ -168,10 +108,10 @@ class ConfigurationSpec extends Specification { def "configuring file #srcDocs in directory #srcDocs is absurd"() { given: "configuration with #srcDir and #srcDocs" - myConfig.addSourceFileConfiguration(srcDir, srcDocs) + myConfig.setSourceConfiguration(srcDir, srcDocs as Set) when: "configuration is validated..." - def tmpResult = myConfig.isValid() + myConfig.isValid() then: "an exception is thrown" thrown MisconfigurationException @@ -181,8 +121,8 @@ class ConfigurationSpec extends Specification { srcDir | srcDocs null | null - new File("/_non/exis_/d_ir/") | null - new File("/_non/exis_/d_ir/") | [] + new File("/_non/exists_/d_ir/") | null + new File("/_non/exists_/d_ir/") | [] // existing but empty directory is absurd too... File.createTempDir() | [] @@ -199,42 +139,26 @@ class ConfigurationSpec extends Specification { thrown MisconfigurationException } - // prefixOnlyHrefExtensions can be reconfigured - def "prefixOnlyHrefExtensions can be overwritten"() { - def newExtensions = ["html", "htm" ] - - when: "prefixOnlyHrefExtensions are overwritten and read" - myConfig.overwritePrefixOnlyHrefExtensions( newExtensions ) - - def prefixOnlyHrefExtensions = myConfig.getConfigItemByName( Configuration.ITEM_NAME_prefixOnlyHrefExtensions) - - then: "prefixOnlyExtensions contain only new elements" - - prefixOnlyHrefExtensions.size() == newExtensions.size() - - prefixOnlyHrefExtensions.contains( newExtensions.get(0)) - } - - @Unroll("checks to execute cannot be #checksToExecute") - def "checks to execute have to be a non empty collection"() { + @Unroll("checks to execute cannot be #checkersToExecute") + def "checks to execute have to be non empty"() { given: tempDir = File.createTempDir() htmlFile = new File(tempDir, "a.html") << HTML_HEADER - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDir, tempDir) - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDocuments, [htmlFile]) - - and: - myConfig.addConfigurationItem(Configuration.ITEM_NAME_checksToExecute, checksToExecute) + Configuration myConfig = Configuration.builder() + .sourceDir(tempDir) + .sourceDocuments([htmlFile] as Set) + .checksToExecute(checkersToExecute) + .build() when: myConfig.valid then: def e = thrown(MisconfigurationException) - e.message == "checks to execute have to be a non empty collection" + e.message == "checks to execute have to be a non-empty list" where: - checksToExecute << [[], "not a collection"] + checkersToExecute << [[] as List] } } diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/BrokenHttpLinksCheckerSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/BrokenHttpLinksCheckerSpec.groovy index 19a3901a..0d5627e1 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/BrokenHttpLinksCheckerSpec.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/BrokenHttpLinksCheckerSpec.groovy @@ -153,7 +153,6 @@ class BrokenHttpLinksCheckerSpec extends Specification { } - def "bad amazon link is identified as problem"() { given: "an HTML page with a single (good) amazon link" @@ -215,7 +214,7 @@ class BrokenHttpLinksCheckerSpec extends Specification { then: "then collector contains one error message" collector.getFindings().size() == 1 - collector?.getFindings()?.first().whatIsTheProblem.contains("https://arc42.de") + collector?.getFindings()?.first()?.whatIsTheProblem?.contains("https://arc42.de") } @@ -237,8 +236,8 @@ class BrokenHttpLinksCheckerSpec extends Specification { then: "warning is given" - collector?.getFindings()?.first().whatIsTheProblem.contains("Warning") - collector?.getFindings()?.first().whatIsTheProblem.contains("suspicious") + collector?.getFindings()?.first()?.whatIsTheProblem?.contains("Warning") + collector?.getFindings()?.first()?.whatIsTheProblem?.contains("suspicious") } } diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/CheckerCreatorSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/CheckerCreatorSpec.groovy index b2230efa..cff0e56a 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/CheckerCreatorSpec.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/CheckerCreatorSpec.groovy @@ -14,7 +14,7 @@ class CheckerCreatorSpec extends Specification { String pMethod - Configuration myConfig = new Configuration() + Configuration myConfig = Configuration.builder().sourceDir(new File('.')).build() def setup() { // ... takes HtmlPage as parameter @@ -44,12 +44,12 @@ class CheckerCreatorSpec extends Specification { Checker oneChecker setup: - ArrayList checkerClazzes = [BrokenCrossReferencesChecker.class, - DuplicateIdChecker.class] + List checkerClazzes = [BrokenCrossReferencesChecker.class, + DuplicateIdChecker.class] when: - checkers = CheckerCreator.createCheckerClassesFrom( checkerClazzes, myConfig ) + checkers = CheckerCreator.createCheckerClassesFrom(checkerClazzes, myConfig) then: checkers.size() == 2 @@ -92,15 +92,15 @@ class CheckerCreatorSpec extends Specification { where: - checkerClazz | superClazz - org.aim42.htmlsanitycheck.check.BrokenCrossReferencesChecker | org.aim42.htmlsanitycheck.check.SuggestingChecker + checkerClazz | superClazz + BrokenCrossReferencesChecker | SuggestingChecker // MIFChecker shall be SuggestingChecker - when issue #113 is fixed! - org.aim42.htmlsanitycheck.check.MissingImageFilesChecker | org.aim42.htmlsanitycheck.check.Checker + MissingImageFilesChecker | Checker - org.aim42.htmlsanitycheck.check.DuplicateIdChecker | org.aim42.htmlsanitycheck.check.Checker - org.aim42.htmlsanitycheck.check.MissingAltInImageTagsChecker | org.aim42.htmlsanitycheck.check.Checker - org.aim42.htmlsanitycheck.check.ImageMapChecker | org.aim42.htmlsanitycheck.check.Checker + DuplicateIdChecker | Checker + MissingAltInImageTagsChecker | Checker + ImageMapChecker | Checker } @@ -108,47 +108,45 @@ class CheckerCreatorSpec extends Specification { def "creating unknown checkers throws exception"() { when: - Checker checker = CheckerCreator.createSingleChecker(java.lang.String.class, myConfig) + CheckerCreator.createSingleChecker(java.lang.String.class, myConfig) then: thrown(UnknownCheckerException) } - - def "can create MissingImageFilesChecker instance"() { + + def "can create MissingImageFilesChecker instance"() { MissingImageFilesChecker oneChecker when: - myConfig.addConfigurationItem( Configuration.ITEM_NAME_sourceDir, new File('.')) - oneChecker = CheckerCreator.createSingleChecker(MissingImageFilesChecker.class, myConfig) + oneChecker = CheckerCreator.createSingleChecker(MissingImageFilesChecker.class, myConfig) as MissingImageFilesChecker // performCheck method returns SingleCheckResults def fullDeclaration = "public org.aim42.htmlsanitycheck.collect.SingleCheckResults org.aim42.htmlsanitycheck.check.Checker.performCheck(org.aim42.htmlsanitycheck.html.HtmlPage)" pMethod = oneChecker.class.getMethod("performCheck", params) - then:'performCheck method is present' + then: 'performCheck method is present' notThrown(NoSuchMethodException) pMethod == fullDeclaration - and:'baseDir is present' - oneChecker.baseDir + and: 'baseDir is present' + oneChecker.baseDir } - def "can create MissingLocalResourcesChecker instance"() { + def "can create MissingLocalResourcesChecker instance"() { MissingLocalResourcesChecker oneChecker when: - myConfig.addConfigurationItem( Configuration.ITEM_NAME_sourceDir, new File('.')) - oneChecker = CheckerCreator.createSingleChecker(MissingLocalResourcesChecker.class, myConfig) + oneChecker = CheckerCreator.createSingleChecker(MissingLocalResourcesChecker.class, myConfig) as MissingLocalResourcesChecker // performCheck method returns SingleCheckResults def fullDeclaration = "public org.aim42.htmlsanitycheck.collect.SingleCheckResults org.aim42.htmlsanitycheck.check.Checker.performCheck(org.aim42.htmlsanitycheck.html.HtmlPage)" pMethod = oneChecker.class.getMethod("performCheck", params) - then:'performCheck method is present' + then: 'performCheck method is present' notThrown(NoSuchMethodException) pMethod == fullDeclaration - and:'baseDir is present' + and: 'baseDir is present' oneChecker.baseDir } } diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/DuplicateIdCheckerTest.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/DuplicateIdCheckerTest.groovy index 240c29d1..a6ce3bdc 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/DuplicateIdCheckerTest.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/DuplicateIdCheckerTest.groovy @@ -1,7 +1,9 @@ package org.aim42.htmlsanitycheck.check import org.aim42.htmlsanitycheck.collect.SingleCheckResults +import org.aim42.htmlsanitycheck.html.HtmlElement import org.aim42.htmlsanitycheck.html.HtmlPage +import org.jsoup.nodes.Element import org.junit.Before import org.junit.Test @@ -17,13 +19,13 @@ class DuplicateIdCheckerTest { SingleCheckResults collector @Before - public void setUp() { + void setUp() { collector = new SingleCheckResults() } @Test - public void testOneDuplicateId() { + void testOneDuplicateId() { String HTML_WITH_DUPLICATE_ID = ''' @@ -46,7 +48,7 @@ class DuplicateIdCheckerTest { } @Test - public void testManyDuplicateId() { + void testManyDuplicateId() { String HTML_WITH_DUPLICATE_ID = ''' @@ -74,7 +76,7 @@ class DuplicateIdCheckerTest { } @Test - public void testGetAllTagsWithSpecificId() { + void testGetAllTagsWithSpecificId() { String HTML_WITH_DUPLICATE_ID = ''' @@ -89,17 +91,17 @@ class DuplicateIdCheckerTest { ''' pageToCheck = new HtmlPage(HTML_WITH_DUPLICATE_ID) - ArrayList tagsWithId = pageToCheck.getAllIds() + List tagsWithId = pageToCheck.getAllIds() //Set idStringsSet = pageToCheck.getAllIdStrings().toSet() assertEquals("Expected 4 tags with ids", 4, tagsWithId.size()) - ArrayList expectedAim43Ids = + List expectedAim43Ids = DuplicateIdChecker.getAllTagsWithSpecificId( "aim43", tagsWithId) assertEquals(" Expected ONE tag with id='aim43", 1, expectedAim43Ids.size() ) - ArrayList expectedAim42Ids = + List expectedAim42Ids = DuplicateIdChecker.getAllTagsWithSpecificId( "aim42", tagsWithId) assertEquals(" Expected TWO tags with id='aim42", 2, expectedAim42Ids.size() ) diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/ImageMapsCheckerSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/ImageMapsCheckerSpec.groovy index 703faf03..18366dd0 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/ImageMapsCheckerSpec.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/ImageMapsCheckerSpec.groovy @@ -24,7 +24,7 @@ class ImageMapsCheckerSpec extends Specification { when: imageMapsChecker = new ImageMapChecker() - collector = imageMapsChecker.performCheck( htmlPage ) + collector = imageMapsChecker.performCheck(htmlPage) then: collector?.getFindingMessages()?.contains(msg) @@ -33,27 +33,27 @@ class ImageMapsCheckerSpec extends Specification { where: - nrOfFindings | imageMapStr | msg + nrOfFindings | imageMapStr | msg // no imagemap, no check, no problem - //0 | """""" | "" + // 0 | """""" | "" // a correct imagemap - //0 | IMG1 + MAP1 + ID1 | "" + // 0 | IMG1 + MAP1 + ID1 | "" // image with usemap-ref but no map! - 1 | IMG1 | """ImageMap "map1" (referenced by image "image1.jpg") missing.""" + 1 | IMG1 | """ImageMap "map1" (referenced by image "image1.jpg") missing.""" // one image but TWO maps with identical name - 1 | IMG1 + MAP1 + MAP1 + ID1 | """2 imagemaps with identical name "map1" exist.""" + 1 | IMG1 + MAP1 + MAP1 + ID1 | """2 imagemaps with identical name "map1" exist.""" // no image, dangling map - 1 | MAP1 + ID1 | """ImageMap "map1" not referenced by any image.""" + 1 | MAP1 + ID1 | """ImageMap "map1" not referenced by any image.""" // empty map - 1 | IMG1 + MAP1_EMPTY | "ImageMap \"map1\" has no area tags." + 1 | IMG1 + MAP1_EMPTY | "ImageMap \"map1\" has no area tags." // href link target missing - 1 | IMG1 + MAP1 + ID2 | "ImageMap \"map1\" refers to missing link \"id1\"." + 1 | IMG1 + MAP1 + ID2 | "ImageMap \"map1\" refers to missing link \"id1\"." } diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingImageFilesCheckerTest.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingImageFilesCheckerTest.groovy index 2be62fbb..0bae08f9 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingImageFilesCheckerTest.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingImageFilesCheckerTest.groovy @@ -31,11 +31,11 @@ class MissingImageFilesCheckerTest { private Configuration myConfig // logging stuff - private final static Logger logger = LoggerFactory.getLogger(MissingImageFilesCheckerTest.class); + private final static Logger logger = LoggerFactory.getLogger(MissingImageFilesCheckerTest.class) @Before - public void setUp() { + void setUp() { userDir = System.getProperty("user.dir") fileName = 'file-to-test.html' @@ -53,13 +53,13 @@ class MissingImageFilesCheckerTest { @Test - public void testCheckImageDirectoryExists() { + void testCheckImageDirectoryExists() { assertTrue( "new image directory $imagesDir does not exist ", new File( imagesDir ).exists()) } @Test - public void testImageMustNotBeDirectory() { + void testImageMustNotBeDirectory() { // we try to use userDir as an image... File userDirectory = new File( userDir ) assertTrue( "userDir does not exist", userDirectory.exists()) @@ -79,7 +79,7 @@ class MissingImageFilesCheckerTest { List images = htmlPage.getAllImageTags() assertEquals( "expected 1 image", 1, images.size()) - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDir, new File("")) + myConfig.setSourceConfiguration(new File(""), [] as Set) checker = new MissingImageFilesChecker( myConfig) checkingResults = checker.performCheck( htmlPage ) @@ -95,7 +95,7 @@ class MissingImageFilesCheckerTest { @Test - public void testExistingImageIsFound() { + void testExistingImageIsFound() { File tempImageFile = File.createTempFile("testfile", ".jpg") << """dummy jpg file""" @@ -111,7 +111,7 @@ class MissingImageFilesCheckerTest { htmlPage = new HtmlPage(HTML_WITH_IMAGE) - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDir, tempImageFile.parentFile ) + myConfig.setSourceConfiguration(tempImageFile.parentFile, [tempImageFile] as Set) checker = new MissingImageFilesChecker( myConfig) checkingResults = checker.performCheck( htmlPage ) @@ -128,7 +128,7 @@ class MissingImageFilesCheckerTest { @Test - public void testCheckSingleImageWithMissingImage() { + void testCheckSingleImageWithMissingImage() { // make sure the generated file exists... assertTrue( "file $filePath does NOT exist (but should!)", @@ -141,7 +141,7 @@ class MissingImageFilesCheckerTest { assertNotNull("htmlpage must not be null", htmlPage ) - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDir, new File(imagesDir) ) + myConfig.setSourceConfiguration(new File(imagesDir), [] as Set) checker = new MissingImageFilesChecker( myConfig) checkingResults = checker.performCheck( htmlPage ) @@ -162,7 +162,7 @@ class MissingImageFilesCheckerTest { } @Test - public void testCheckAbsoluteImage() { + void testCheckAbsoluteImage() { File tempFolder = File.createTempDir() File imageFolder = new File(tempFolder, "images") @@ -179,7 +179,7 @@ class MissingImageFilesCheckerTest { List images = htmlPage.getAllImageTags() assertEquals( "expected 1 image", 1, images.size()) - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDir, tempFolder ) + myConfig.setSourceConfiguration(tempFolder, [] as Set) checker = new MissingImageFilesChecker( myConfig) checkingResults = checker.performCheck( htmlPage ) @@ -198,7 +198,7 @@ class MissingImageFilesCheckerTest { } @Test - public void testCheckImageWithSpace() { + void testCheckImageWithSpace() { File tempFolder = File.createTempDir() File imageFolder = new File(tempFolder, "images") @@ -215,7 +215,7 @@ class MissingImageFilesCheckerTest { List images = htmlPage.getAllImageTags() assertEquals( "expected 1 image", 1, images.size()) - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDir, tempFolder ) + myConfig.setSourceConfiguration(tempFolder, [] as Set) checker = new MissingImageFilesChecker( myConfig) checkingResults = checker.performCheck( htmlPage ) diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingLocalResourceRefCountSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingLocalResourceRefCountSpec.groovy index 783c44dc..aee66e08 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingLocalResourceRefCountSpec.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingLocalResourceRefCountSpec.groovy @@ -1,5 +1,6 @@ package org.aim42.htmlsanitycheck.check +import groovy.util.logging.Slf4j import org.aim42.htmlsanitycheck.Configuration import org.aim42.htmlsanitycheck.collect.SingleCheckResults import org.aim42.htmlsanitycheck.html.HtmlConst @@ -7,12 +8,13 @@ import org.aim42.htmlsanitycheck.html.HtmlPage import spock.lang.Specification import spock.lang.Unroll +@Slf4j class MissingLocalResourceRefCountSpec extends Specification { // missing local resource name private static final String MIS_LOC_RES = "MissingLocalResource.html" - private static final String badLocalRef = """missing""" + private static final String badLocalRef = """missing""" private static final String msgPrefix = MissingLocalResourcesChecker.MLRC_MESSAGE_PREFIX @@ -45,6 +47,7 @@ class MissingLocalResourceRefCountSpec extends Specification { String htmlSnippet, String result) { + log.debug "testing with $nrOfChecks, $nrOfFindings, $htmlSnippet, expected: $result" given: String html = HtmlConst.HTML_HEAD + htmlSnippet + HtmlConst.HTML_END @@ -52,19 +55,16 @@ class MissingLocalResourceRefCountSpec extends Specification { // create a file (tmpHtmlFile, tmpDir) = createTempLocalResources("index.html", html) - HtmlPage htmlPage = new HtmlPage( tmpHtmlFile ) + HtmlPage htmlPage = new HtmlPage(tmpHtmlFile) - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDir, tmpDir ) + myConfig.setSourceConfiguration(tmpDir, [tmpHtmlFile] as Set) when: - def missingLocalResourcesChecker = new MissingLocalResourcesChecker( myConfig ) - SingleCheckResults collector = missingLocalResourcesChecker.performCheck( htmlPage ) + def missingLocalResourcesChecker = new MissingLocalResourcesChecker(myConfig) + SingleCheckResults collector = missingLocalResourcesChecker.performCheck(htmlPage) then: - - println "testing with $nrOfChecks, $nrOfFindings, $htmlSnippet, expected: $result " - // our temporary files still exists tmpHtmlFile.exists() @@ -78,22 +78,22 @@ class MissingLocalResourceRefCountSpec extends Specification { where: - nrOfChecks | nrOfFindings | htmlSnippet | result - // one bad local reference: - 1 | 1 | badLocalRef | """${msgPrefix} "${MIS_LOC_RES}" ${msgMissing}""" + nrOfChecks | nrOfFindings | htmlSnippet | result + // one bad local reference: + 1 | 1 | badLocalRef | """${msgPrefix} "${MIS_LOC_RES}" ${msgMissing}""" // two bad local references to the same file -> reference count == 2 - 1 | 2 | badLocalRef*2 | """${msgPrefix} "${MIS_LOC_RES}" ${msgMissing}${msgRefCount}2""" + 1 | 2 | badLocalRef * 2 | """${msgPrefix} "${MIS_LOC_RES}" ${msgMissing}${msgRefCount}2""" // five bad local references to the same file -> reference count == 5 - 1 | 5 | badLocalRef*5 | """${msgPrefix} "${MIS_LOC_RES}" ${msgMissing}${msgRefCount}5""" + 1 | 5 | badLocalRef * 5 | """${msgPrefix} "${MIS_LOC_RES}" ${msgMissing}${msgRefCount}5""" } /* - * helper to create local resource + * helper to create local resource */ - def List createTempLocalResources(String htmlFileName, String htmlContent) { + List createTempLocalResources(String htmlFileName, String htmlContent) { // 1.) create tmp directory tmpDir File tmpDir = File.createTempDir() diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingLocalResourcesCheckerSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingLocalResourcesCheckerSpec.groovy index 534c51ba..e2a6e501 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingLocalResourcesCheckerSpec.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingLocalResourcesCheckerSpec.groovy @@ -43,7 +43,7 @@ class MissingLocalResourcesCheckerSpec extends Specification { File exampleFile = new File(d1, "example.html") << HtmlConst.HTML_HEAD + HtmlConst.HTML_END // 4.) configure checker with temp directory - myConfig.addConfigurationItem( Configuration.ITEM_NAME_sourceDir, d1) + myConfig.setSourceConfiguration(d1, [exampleFile] as Set) missingLocalResourcesChecker = new MissingLocalResourcesChecker(myConfig) // 5.) diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingLocalResourcesCheckerTest.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingLocalResourcesCheckerTest.groovy index b0cac07f..dd78b132 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingLocalResourcesCheckerTest.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/MissingLocalResourcesCheckerTest.groovy @@ -20,7 +20,7 @@ class MissingLocalResourcesCheckerTest { private Configuration myConfig @Before - public void setUp() { + void setUp() { collector = new SingleCheckResults() myConfig = new Configuration() } @@ -30,7 +30,7 @@ class MissingLocalResourcesCheckerTest { * test that we can find a referenced local file in subdirectory */ @Test - public void testExistingLocalResourceIsFound() { + void testExistingLocalResourceIsFound() { def (File index, String fname, File d1) = createNestedTempDirWithFile() @@ -38,8 +38,7 @@ class MissingLocalResourcesCheckerTest { assertTrue( "newly created html file exists", index.exists()) - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDir, d1 ) - + myConfig.setSourceConfiguration(d1, [index] as Set) htmlPage = new HtmlPage( index ) @@ -57,7 +56,7 @@ class MissingLocalResourcesCheckerTest { * a "complex" local reference is an anchor of the form dummy-heading-1 aim42 @@ -110,7 +109,7 @@ class MissingLocalResourcesCheckerTest { @Test - public void testReferenceToLocalFileIsChecked() { + void testReferenceToLocalFileIsChecked() { String HTML = """${HtmlConst.HTML_HEAD}

dummy-heading-1

nonexisting-doc @@ -119,7 +118,7 @@ class MissingLocalResourcesCheckerTest { htmlPage = new HtmlPage( HTML ) - myConfig.addConfigurationItem( Configuration.ITEM_NAME_sourceDir, new File(".")) + myConfig.setSourceConfiguration(new File("."), [] as Set) missingLocalResourcesChecker = new MissingLocalResourcesChecker(myConfig) collector = missingLocalResourcesChecker.performCheck( htmlPage ) @@ -135,7 +134,7 @@ class MissingLocalResourcesCheckerTest { helper to created nested directory structure */ - private List createNestedTempDirWithFile() { + private static List createNestedTempDirWithFile() { // 1.) create tmp directory d1 with subdir d2 File d1 = File.createTempDir() File d2 = new File(d1, "/d2") @@ -161,7 +160,7 @@ class MissingLocalResourcesCheckerTest { @Test - public void testCheckAbsoluteResource() { + void testCheckAbsoluteResource() { File tempFolder = File.createTempDir() File filesFolder = new File(tempFolder, "files") @@ -173,7 +172,7 @@ class MissingLocalResourcesCheckerTest {

""" - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDir, tempFolder ) + myConfig.setSourceConfiguration(tempFolder, [htmlFile] as Set) htmlPage = new HtmlPage( htmlFile ) diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/collect/SingleCheckResultsTest.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/collect/SingleCheckResultsTest.groovy index 99f9886a..0d451d07 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/collect/SingleCheckResultsTest.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/collect/SingleCheckResultsTest.groovy @@ -19,16 +19,14 @@ class SingleCheckResultsTest { final String localPath = "/src/test/resources" - private Configuration myConfig = new Configuration() - - String imageDir + File imageDir SingleCheckResults checkingResults Checker checker @Before - public void setUp() { + void setUp() { checkingResults = new SingleCheckResults( whatIsChecked: whatIsCheckedMessage @@ -37,14 +35,11 @@ class SingleCheckResultsTest { // not working in IntelliJ multi-module setup // imagesDir = System.getProperty("user.dir") + localPath - imageDir = new File(".").getCanonicalPath() + localPath - - myConfig.addConfigurationItem(Configuration.ITEM_NAME_sourceDir, new File(imageDir) ) - + imageDir = new File (new File(".").getCanonicalPath(), localPath) } @Test - public void testCheckingResultConstruction() { + void testCheckingResultConstruction() { String expected = "empty checkingResult shall have " assertEquals(expected + "proper whatIsChecked", @@ -57,7 +52,7 @@ class SingleCheckResultsTest { } @Test - public void testAddManyFindingToCheckingResult() { + void testAddManyFindingToCheckingResult() { int maxNrOfFindinds = 2 for (int i = 1; i < maxNrOfFindinds; i++) { @@ -67,7 +62,7 @@ class SingleCheckResultsTest { } @Test - public void testAddFindingToCheckingResult() { + void testAddFindingToCheckingResult() { checkingResults.addFinding(new Finding("googlygoob")) String expected = "One finding expected" @@ -75,7 +70,7 @@ class SingleCheckResultsTest { } @Test - public void testCheckTwoImageTagsOneMissingFile() { + void testCheckTwoImageTagsOneMissingFile() { String oneGoodOneBadImageHTML = """

dummy-heading-1

@@ -88,7 +83,7 @@ class SingleCheckResultsTest { List images = htmlPage.getAllImageTags() assertEquals("expected 2 images", 2, images.size()) - checker = new MissingImageFilesChecker( myConfig ) + checker = new MissingImageFilesChecker( Configuration.builder().sourceDir(imageDir).build() ) SingleCheckResults checkingResults = checker.performCheck( htmlPage ) diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/HtmlPageSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/HtmlPageSpec.groovy index 6daf94fc..ead849dd 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/HtmlPageSpec.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/HtmlPageSpec.groovy @@ -6,7 +6,7 @@ import spock.lang.Unroll class HtmlPageSpec extends Specification { private HtmlPage htmlPage - private ArrayList qualifiedImageTags + private List qualifiedImageTags @Unroll @@ -73,7 +73,7 @@ class HtmlPageSpec extends Specification { @Unroll def "detect correct number of external http links in anchors '#anchors' "() { - ArrayList externalLinks + Set externalLinks when: String html = HtmlConst.HTML_HEAD + anchors + HtmlConst.HTML_END diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/HtmlPageTest.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/HtmlPageTest.groovy index e108a773..b440f4b2 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/HtmlPageTest.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/HtmlPageTest.groovy @@ -1,8 +1,8 @@ package org.aim42.htmlsanitycheck.html +import org.aim42.htmlsanitycheck.tools.Web import org.junit.Before import org.junit.Test -import org.aim42.htmlsanitycheck.tools.Web import static org.junit.Assert.assertEquals import static org.junit.Assert.assertTrue @@ -51,12 +51,12 @@ class HtmlPageTest { @Before - public void setUp() { + void setUp() { tmpFile = File.createTempFile("testfile", "html") } @Test - public void testStaticParseHtml() { + void testStaticParseHtml() { tmpFile.write(HTML_WITH_TWO_IMG_TAGS) htmlPage = HtmlPage.parseHtml(tmpFile) @@ -68,11 +68,11 @@ class HtmlPageTest { @Test - public void testGetTwoImagesFromHtml() { + void testGetTwoImagesFromHtml() { htmlPage = new HtmlPage(HTML_WITH_TWO_IMG_TAGS) - ArrayList images = htmlPage.getAllImageTags() + List images = htmlPage.getAllImageTags() // should yield TWO image tags! assertEquals("TWO images expected", 2, images.size()) @@ -82,11 +82,11 @@ class HtmlPageTest { @Test - public void testGetOneImageFromHtml() { + void testGetOneImageFromHtml() { htmlPage = new HtmlPage(HTML_WITH_ONE_IMG_TAG) - ArrayList images = htmlPage.getAllImageTags() + List images = htmlPage.getAllImageTags() // should yield exactly ONE image tag! assertEquals("ONE image expected", 1, images.size()) @@ -94,12 +94,12 @@ class HtmlPageTest { } @Test - public void testGetOneImageFromHtmlFile() { + void testGetOneImageFromHtmlFile() { tmpFile.write(HTML_WITH_ONE_IMG_TAG) htmlPage = new HtmlPage(tmpFile) - ArrayList images = htmlPage.getAllImageTags() + List images = htmlPage.getAllImageTags() // should yield exactly ONE image tag! assertEquals("ONE image expected", 1, images.size()) @@ -107,12 +107,12 @@ class HtmlPageTest { } @Test - public void testGetTwoImagesFromHtmlFile() { + void testGetTwoImagesFromHtmlFile() { tmpFile.write(HTML_WITH_TWO_IMG_TAGS) htmlPage = new HtmlPage(tmpFile) - ArrayList images = htmlPage.getAllImageTags() + List images = htmlPage.getAllImageTags() assertEquals("two images expected", 2, images.size()) @@ -120,7 +120,7 @@ class HtmlPageTest { @Test - public void testGetHtmlImgTagsFromFile() { + void testGetHtmlImgTagsFromFile() { String userDir = System.getProperty("user.dir") String filePath = userDir + LOCAL_PATH + FILENAME @@ -130,13 +130,13 @@ class HtmlPageTest { htmlPage = new HtmlPage(new File(filePath)) - ArrayList images = htmlPage.getAllImageTags() + List images = htmlPage.getAllImageTags() assertEquals("expected 4 images", 4, images.size()) } @Test - public void testGetLocalAnchorHrefsFromHtml() { + void testGetLocalAnchorHrefsFromHtml() { String HREF_ONE = "#aim42" String HREF_TWO = "#nonexisting" @@ -152,7 +152,7 @@ class HtmlPageTest { htmlPage = new HtmlPage(HTML_WITH_A_TAGS_AND_ID) - ArrayList anchors = htmlPage.getAllAnchorHrefs() + List anchors = htmlPage.getAllAnchorHrefs() assertEquals("two anchor hrefs expected", 2, anchors.size()) @@ -162,7 +162,7 @@ class HtmlPageTest { } @Test - public void testGetLocalAndRemoteAnchorsFromHtml() { + void testGetLocalAndRemoteAnchorsFromHtml() { String ONE = "downloads/aim42.pdf" String TWO = "File.docx" @@ -176,7 +176,7 @@ class HtmlPageTest { htmlPage = new HtmlPage(HTML) - ArrayList anchors = htmlPage.getAllAnchorHrefs() + List anchors = htmlPage.getAllAnchorHrefs() assertEquals("three anchor hrefs expected", 3, anchors.size()) @@ -189,7 +189,7 @@ class HtmlPageTest { * make sure we get the hrefs (id="XYZ") from html **/ @Test - public void testGetOneIdFromHtml() { + void testGetOneIdFromHtml() { String HREF_ONE = "aim42" @@ -200,7 +200,7 @@ class HtmlPageTest { htmlPage = new HtmlPage(HTML_WITH_A_TAG_AND_ID) - ArrayList bookmarks = htmlPage.getAllIds() + List bookmarks = htmlPage.getAllIds() // there's ONE id contained in the sample html assertEquals("only ONE id is expected in bookmark list", 1, bookmarks.size()) @@ -210,7 +210,7 @@ class HtmlPageTest { } @Test - public void testGetManyIdFromHtml() { + void testGetManyIdFromHtml() { String HREF_ONE = "aim42" @@ -226,7 +226,7 @@ class HtmlPageTest { ''' htmlPage = new HtmlPage(HTML_WITH_A_TAG_AND_ID) - ArrayList bookmarks = htmlPage.getAllIds() + List bookmarks = htmlPage.getAllIds() // there's TWO ids contained in the sample html assertEquals("TWO ids expected in bookmark list", 3, bookmarks.size()) @@ -235,7 +235,7 @@ class HtmlPageTest { @Test - public void testAnchorsToStringList() { + void testAnchorsToStringList() { String HTML_WITH_A_TAGS_AND_ID = ''' $HTML_PREFIX @@ -248,7 +248,7 @@ class HtmlPageTest { ''' htmlPage = new HtmlPage(HTML_WITH_A_TAGS_AND_ID) - ArrayList hrefs = htmlPage.getAllHrefStrings() + List hrefs = htmlPage.getAllHrefStrings() assertEquals("expected [#aim42, #nonexisting]", ['#aim42', '#nonexisting'], hrefs) @@ -261,7 +261,7 @@ class HtmlPageTest { */ @Test - public void testGetAllLocalResourceHrefStrings() { + void testGetAllLocalResourceHrefStrings() { final String LOC1 = "file://path/filename.html" final String LOC2 = "dir/ectory/filename.pdf" @@ -273,7 +273,7 @@ class HtmlPageTest { """ htmlPage = new HtmlPage(HTML) - ArrayList hrefs = htmlPage.getAllHrefStrings() + List hrefs = htmlPage.getAllHrefStrings() assertEquals("expected 3 href-strings", 3, hrefs.size()) @@ -287,7 +287,7 @@ class HtmlPageTest { @Test - public void testGetManyIdStrings() { + void testGetManyIdStrings() { String HTML_WITH_A_TAGS_AND_ID = ''' $HTML_PREFIX @@ -302,7 +302,7 @@ class HtmlPageTest { ''' htmlPage = new HtmlPage(HTML_WITH_A_TAGS_AND_ID) - ArrayList ids = htmlPage.getAllIdStrings() + List ids = htmlPage.getAllIdStrings() def expected = ['aim42', 'aim43', 'aim44', 'aim45', 'aim46'] assertEquals("expected $expected", expected, ids) @@ -310,7 +310,7 @@ class HtmlPageTest { @Test - public void testGetIdStringsAndAllIds() { + void testGetIdStringsAndAllIds() { String HTML_WITH_A_TAGS_AND_ID = """$HTML_HEAD
link-to-aim42

aim42 Architecture Improvement

@@ -320,12 +320,12 @@ class HtmlPageTest { """ htmlPage = new HtmlPage(HTML_WITH_A_TAGS_AND_ID) - ArrayList idStrings = htmlPage.getAllIdStrings() + List idStrings = htmlPage.getAllIdStrings() def expectedIdStrings = ['aim42', 'aim43', 'aim44'] assertEquals("expected $expectedIdStrings", expectedIdStrings, idStrings) - ArrayList tagsWithId = htmlPage.getAllIds() + List tagsWithId = htmlPage.getAllIds() assertEquals("expected 3 tags with ids", 3, tagsWithId.size()) } @@ -339,7 +339,7 @@ class HtmlPageTest { * ( */ @Test - public void testManyAnchorTags() { + void testManyAnchorTags() { final int NR_OF_ANCHORS = 3000 diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/HtmlParserTest.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/HtmlParserTest.groovy index 578ca202..f530ea3e 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/HtmlParserTest.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/HtmlParserTest.groovy @@ -25,7 +25,7 @@ class HtmlParserTest { @Test - public void testBasicParser() { + void testBasicParser() { String html = ''' @@ -35,9 +35,9 @@ class HtmlParserTest {

very basic html

- '''; + ''' - Document doc = Jsoup.parse(html); + Document doc = Jsoup.parse(html) boolean actual = (doc.body() != null) assertTrue("parsed basic html doc contains body", actual) @@ -45,11 +45,11 @@ class HtmlParserTest { @Test - public void testGetSrcAttributeFromImageTag() { + void testGetSrcAttributeFromImageTag() { HtmlPage htmlpage = new HtmlPage(HTML_WITH_IMG_TAG) - ArrayList imageTags = htmlpage.getAllImageTags() + List imageTags = htmlpage.getAllImageTags() assertEquals("expect exactly one image tag", 1, imageTags.size()) @@ -61,7 +61,7 @@ class HtmlParserTest { @Test - public void testGetSrcAttributeFromRemoteImageTag() { + void testGetSrcAttributeFromRemoteImageTag() { String HTML = """${HtmlConst.HTML_HEAD} @@ -71,7 +71,7 @@ class HtmlParserTest { HtmlPage htmlPage = new HtmlPage( HTML ) - ArrayList imageTags = htmlPage.getAllImageTags() + List imageTags = htmlPage.getAllImageTags() String expected = REMOTE_IMG_SRC String actual = imageTags.first().getImageSrcAttribute() @@ -81,7 +81,7 @@ class HtmlParserTest { } @Test - public void testGetHrefFromAnchorTag() { + void testGetHrefFromAnchorTag() { final String REMOTE_URL = "http://github.com/aim42" final String HTML = """${HtmlConst.HTML_HEAD} diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/ImageMapParserSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/ImageMapParserSpec.groovy index e48901f3..1da1e46e 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/ImageMapParserSpec.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/ImageMapParserSpec.groovy @@ -1,5 +1,6 @@ package org.aim42.htmlsanitycheck.html +import org.jsoup.nodes.Element import spock.lang.Specification import spock.lang.Unroll @@ -28,13 +29,11 @@ class ImageMapParserSpec extends Specification { // find all imageMaps within pageToCheck @Unroll def "find all maps within page"(int nrOfIMaps, String imageMapString) { - ArrayList imageMaps = new ArrayList() - when: String html = HtmlConst.HTML_HEAD + imageMapString + HtmlConst.HTML_END htmlPage = new HtmlPage(html) - imageMaps = htmlPage.getAllImageMaps() + def imageMaps = htmlPage.getAllImageMaps() then: imageMaps.size() == nrOfIMaps @@ -55,7 +54,7 @@ class ImageMapParserSpec extends Specification { // find all img-tags with usemap-reference @Unroll def "find all image tags with usemap declaration"(int nrOfImgs, String htmlBody) { - ArrayList imageTagsWithUsemap + List imageTagsWithUsemap when: String html = HtmlConst.HTML_HEAD + htmlBody + HtmlConst.HTML_END @@ -75,13 +74,13 @@ class ImageMapParserSpec extends Specification { } /** - ** find all mapNames (Strings...), + ** find all mapNames (Strings...), * by inspecting the map-tags - */ + */ @Unroll - def "find all map names within page"(String htmlBody, ArrayList names) { - ArrayList mapNames + def "find all map names within page"(String htmlBody, List names) { + List mapNames when: String html = HtmlConst.HTML_HEAD + htmlBody + HtmlConst.HTML_END @@ -108,8 +107,8 @@ class ImageMapParserSpec extends Specification { * by searching the img-tags for usemap-attributes */ @Unroll - def "find all usemap references within page"(String htmlBody, ArrayList names) { - ArrayList usemapRefs + def "find all usemap references within page"(String htmlBody, List names) { + List usemapRefs when: String html = HtmlConst.HTML_HEAD + htmlBody + HtmlConst.HTML_END @@ -134,7 +133,7 @@ class ImageMapParserSpec extends Specification { // find the area-tags within a named imageMap def "find all areas within map"(int nrOfAreas, String mapName, String htmlBody) { - ArrayList areasInMap + List areasInMap when: String html = HtmlConst.HTML_HEAD + htmlBody + HtmlConst.HTML_END @@ -150,18 +149,18 @@ class ImageMapParserSpec extends Specification { nrOfAreas | mapName | htmlBody // 2 areas in one imageMap - 2 | "mymap" | ONE_IMG_ONE_MAP_TWO_AREAS + 2 | "mymap" | ONE_IMG_ONE_MAP_TWO_AREAS // 1 area in named map, 2 in other - 1 | "mymap" | ONE_IMG_ONE_MAP_ONE_AREA + 1 | "mymap" | ONE_IMG_ONE_MAP_ONE_AREA } // find the area-tags within a named imageMap - def "find all hrefs within map"(int nrOfHrefs, String mapName, String htmlBody, ArrayList hrefs) { - ArrayList hrefsInMap + def "find all hrefs within map"(int nrOfHrefs, String mapName, String htmlBody, List hrefs) { + List hrefsInMap when: String html = HtmlConst.HTML_HEAD + htmlBody + HtmlConst.HTML_END @@ -172,18 +171,17 @@ class ImageMapParserSpec extends Specification { then: // size matters nrOfHrefs == hrefsInMap.size() - - + hrefsInMap == hrefs where: - nrOfHrefs | mapName | htmlBody | hrefs + nrOfHrefs | mapName | htmlBody | hrefs // 2 areas in one imageMap | - 2 | "mymap" | ONE_IMG_ONE_MAP_TWO_AREAS | ["#test1", "#test2"] + 2 | "mymap" | ONE_IMG_ONE_MAP_TWO_AREAS | ["#test1", "#test2"] // 1 area in named map, 2 in other - 1 | "mymap" | ONE_IMG_ONE_MAP_ONE_AREA | ["#test1"] + 1 | "mymap" | ONE_IMG_ONE_MAP_ONE_AREA | ["#test1"] } diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/report/SummarizerUtilSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/report/SummarizerUtilSpec.groovy index 6c1417f7..0c7898a7 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/report/SummarizerUtilSpec.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/report/SummarizerUtilSpec.groovy @@ -64,7 +64,7 @@ class SummarizerUtilSpec extends Specification { 10 | 0 | 100 10 | 2 | 80 10 | 3 | 70 - 3 | 1 | 66 + 3 | 1 | 67 3 | 2 | 33 200 | 99 | 50 1000 | 250 | 75 @@ -101,7 +101,7 @@ class SummarizerUtilSpec extends Specification { // helper method - private void setNrOfFindings(int nrOfFindings, SingleCheckResults scr) { + private static void setNrOfFindings(int nrOfFindings, SingleCheckResults scr) { Finding finding = new Finding("a finding") for (int i = 0; i < nrOfFindings; i++) { diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/suggest/SuggesterSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/suggest/SuggesterSpec.groovy index 99eb4bb7..947db622 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/suggest/SuggesterSpec.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/suggest/SuggesterSpec.groovy @@ -6,7 +6,7 @@ import spock.lang.Timeout class SuggesterSpec extends Specification { - private ArrayList options + private List options private String target private List suggestions @@ -76,7 +76,7 @@ class SuggesterSpec extends Specification { // wait max one second def "Find Suggestion in Long Option List"() { final int HALFLENGTH = 1001 - ArrayList longOptionList = new ArrayList(2 * HALFLENGTH) + List longOptionList = new ArrayList(2 * HALFLENGTH) given: target = "HtmlSanitY" @@ -118,7 +118,7 @@ class SuggesterSpec extends Specification { final String bestOption = "hsc-logo.jpg" final String secondOption = "hsclogo.jpg" - ArrayList optionList = ["arc42-logo.jpg", + List optionList = ["arc42-logo.jpg", "hsc-logo-shaded.png", bestOption, secondOption, diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/URLUtilSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/tools/WebSpec.groovy similarity index 58% rename from htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/URLUtilSpec.groovy rename to htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/tools/WebSpec.groovy index c2495065..3ad029a9 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/html/URLUtilSpec.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/tools/WebSpec.groovy @@ -1,35 +1,75 @@ -package org.aim42.htmlsanitycheck.html +package org.aim42.htmlsanitycheck.tools -import org.aim42.htmlsanitycheck.tools.Web import spock.lang.Specification import spock.lang.Unroll -class URLUtilSpec extends Specification { +// see end-of-file for license information + + +class WebSpec extends Specification { + + @Unroll + def "success return codes contain #successCode"() { + expect: + Web.isSuccessCode(successCode) + + where: + successCode << [200, 201, 202] + } + + @Unroll + def "warning return codes contain #warningCode"() { + expect: + Web.isWarningCode(warningCode) + + where: + warningCode << [100, 101, 102] + } + + @Unroll + def "error codes contain #errorCode"() { + expect: + Web.isErrorCode(errorCode) + + where: + errorCode << [400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 500, 501, 502, 503, 504, 505] + } + + def "is internet connection available"() { + + // Stubbing in the following manner DOES NOT WORK!!! + //given: "we're disconnected from the internet..." + //Stub(NetUtil) + //NetUtil.isInternetConnectionAvailable(_) >> false + + + expect: + Web.isInternetConnectionAvailable() + } //@Unroll def "invalid chars in link"(boolean containsInvalidChars, String link) { expect: - Web.containsInvalidChars( link ) == containsInvalidChars + Web.containsInvalidChars(link) == containsInvalidChars where: containsInvalidChars | link - false | "#Context-Analysis" - false | "#Context_Analysis" - false | "#Context--Analysis" - false | "/forum/#!forum/randoop-discuss" // correct, as reported in #271 + false | "#Context-Analysis" + false | "#Context_Analysis" + false | "#Context--Analysis" + false | "/forum/#!forum/randoop-discuss" // correct, as reported in #271 - true | "#Context Analysis" // regression test, contains blank - true | "*Context-Analysis" // * is not allowed + true | "#Context Analysis" // regression test, contains blank + true | "*Context-Analysis" // * is not allowed } - @Unroll def "identify invalid links"(boolean isValid, String link) { expect: - Web.isValidURL( link ) == isValid + Web.isValidURL(link) == isValid where: @@ -47,7 +87,7 @@ class URLUtilSpec extends Specification { def "identify local resource links"(boolean isLocal, String link) { expect: - Web.isLocalResource( link ) == isLocal + Web.isLocalResource(link) == isLocal where: @@ -105,25 +145,4 @@ class URLUtilSpec extends Specification { } -} - - -/************************************************************************ - * This is free software - without ANY guarantee! - * - * - * Copyright 2013-2015, Dr. Gernot Starke, arc42.org - * - * 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. - * - *********************************************************************** */ +} \ No newline at end of file diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/inet/NetUtilSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/inet/NetUtilSpec.groovy deleted file mode 100644 index a9c98a54..00000000 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/inet/NetUtilSpec.groovy +++ /dev/null @@ -1,42 +0,0 @@ -package org.aim42.inet - -import org.aim42.htmlsanitycheck.tools.Web -import spock.lang.Specification -import spock.lang.Unroll - - -// see end-of-file for license information - - -class NetUtilSpec extends Specification { - - @Unroll - def "success return codes contain #successCode"() { - expect: - successCode in Web.HTTP_SUCCESS_CODES - - where: - successCode << [200,201,202] - } - - @Unroll - def "error codes contain #errorCode"() { - expect: - errorCode in Web.HTTP_ERROR_CODES - - where: - errorCode << [400,401,402,403,404,405,406,407,408,409,410,500,501,502,503,504,505] - } - - def "is internet connection available"() { - - // Stubbing in the following manner DOES NOT WORK!!! - //given: "we're disconnected from the internet..." - //Stub(NetUtil) - //NetUtil.isInternetConnectionAvailable(_) >> false - - - expect: - Web.isInternetConnectionAvailable() == true - } -} \ No newline at end of file diff --git a/htmlSanityCheck-gradle-plugin/src/main/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTask.groovy b/htmlSanityCheck-gradle-plugin/src/main/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTask.groovy index 3cb9d872..0c5938ae 100644 --- a/htmlSanityCheck-gradle-plugin/src/main/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTask.groovy +++ b/htmlSanityCheck-gradle-plugin/src/main/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTask.groovy @@ -66,16 +66,16 @@ class HtmlSanityCheckTask extends DefaultTask { // shall certain http status codes be treated differently from the standard? @Optional @Input - Collection httpWarningCodes + Set httpWarningCodes @Optional @Input - Collection httpErrorCodes + Set httpErrorCodes @Optional @Input - Collection httpSuccessCodes + Set httpSuccessCodes @Input - Set checkerClasses = AllCheckers.checkerClazzes + List checkerClasses = AllCheckers.CHECKER_CLASSES // private stuff // ************************************************************************** @@ -117,13 +117,13 @@ class HtmlSanityCheckTask extends DefaultTask { * @author Gernot Starke */ @TaskAction - public void sanityCheckHtml() { + void sanityCheckHtml() { // tell us about these parameters logBuildParameter() // get configuration parameters from gradle - myConfig = this.setupConfiguration() + myConfig = setupConfiguration() // if we have no valid configuration, abort with exception if (myConfig.isValid()) { @@ -176,31 +176,35 @@ See ${checkingResultsDir} for a detailed report.""" */ protected Configuration setupConfiguration() { - Configuration tmpConfig = new Configuration() + Configuration result = Configuration.builder() + .sourceDocuments(sourceDocuments.files) + .sourceDir(sourceDir) + .checkingResultsDir(checkingResultsDir) + .junitResultsDir(junitResultsDir) - tmpConfig.with { - addConfigurationItem(Configuration.ITEM_NAME_sourceDocuments, sourceDocuments.files) - addConfigurationItem(Configuration.ITEM_NAME_sourceDir, sourceDir) - addConfigurationItem(Configuration.ITEM_NAME_checkingResultsDir, checkingResultsDir) - addConfigurationItem(Configuration.ITEM_NAME_junitResultsDir, junitResultsDir) + // consoleReport is always FALSE for Gradle based builds + .consoleReport(false) + .failOnErrors(failOnErrors) + .httpConnectionTimeout(httpConnectionTimeout) - // consoleReport is always FALSE for Gradle based builds - addConfigurationItem(Configuration.ITEM_NAME_consoleReport, false) - addConfigurationItem(Configuration.ITEM_NAME_failOnErrors, failOnErrors) - addConfigurationItem(Configuration.ITEM_NAME_httpConnectionTimeout, httpConnectionTimeout) + .ignoreLocalhost(ignoreLocalHost) + .ignoreIPAddresses(ignoreIPAddresses) - addConfigurationItem(Configuration.ITEM_NAME_ignoreLocalhost, ignoreLocalHost) - addConfigurationItem(Configuration.ITEM_NAME_ignoreIPAddresses, ignoreIPAddresses) + .checksToExecute(checkerClasses) + .build() - addConfigurationItem(Configuration.ITEM_NAME_checksToExecute, checkerClasses) - - // in case we have configured specific interpretations of http status codes - overwriteHttpSuccessCodes(httpSuccessCodes) - overwriteHttpErrorCodes(httpErrorCodes) - overwriteHttpWarningCodes(httpWarningCodes) + // in case we have configured specific interpretations of http status codes + if (httpSuccessCodes) { + result.overrideHttpSuccessCodes(httpSuccessCodes) + } + if (httpErrorCodes) { + result.overrideHttpErrorCodes(httpErrorCodes) + } + if (httpWarningCodes) { + result.overrideHttpWarningCodes(httpWarningCodes) } - return tmpConfig + return result } diff --git a/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskFunctionalTest.groovy b/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskFunctionalTest.groovy index 3698302d..99ac8481 100644 --- a/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskFunctionalTest.groovy +++ b/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskFunctionalTest.groovy @@ -115,7 +115,7 @@ class HtmlSanityCheckTaskFunctionalTest extends Specification { import org.aim42.htmlsanitycheck.check.AllCheckers htmlSanityCheck { - checkerClasses = [AllCheckers.checkerClazzes.first()] + checkerClasses = [AllCheckers.CHECKER_CLASSES.first()] } """ diff --git a/sandbox/imageMapsParser.groovy b/sandbox/imageMapsParser.groovy index 19d54abc..2d82ef49 100644 --- a/sandbox/imageMapsParser.groovy +++ b/sandbox/imageMapsParser.groovy @@ -32,8 +32,8 @@ def Elements getMapsByName( Document doc, String mapName ) { return doc.select("""map[name=${mapName}]""") } -def ArrayList getHrefsForMap( Element map) { - ArrayList hrefs = new ArrayList() +def List getHrefsForMap( Element map) { + List hrefs = new ArrayList() getAreasForMap( map )?.each{ area -> hrefs += area.attr("href") @@ -98,7 +98,7 @@ maps.each { oneMap -> // 3.) are there hrefs defined within areas? - ArrayList hrefs = getHrefsForMap( oneMap ) + List hrefs = getHrefsForMap( oneMap ) println "hrefs = " + hrefs diff --git a/src/docs/development/issue-185.adoc b/src/docs/development/issue-185.adoc index c94c1406..31754b0b 100644 --- a/src/docs/development/issue-185.adoc +++ b/src/docs/development/issue-185.adoc @@ -21,7 +21,7 @@ major redundancies in code: ---- class AllCheckers { - public final static LinkedHashSet checkerClazzes = + public final static Set checkerClazzes = [BrokenCrossReferencesChecker, BrokenHttpLinksChecker, DuplicateIdChecker, diff --git a/src/docs/development/issue-252.adoc b/src/docs/development/issue-252.adoc index 4cc5dabf..39f938d1 100644 --- a/src/docs/development/issue-252.adoc +++ b/src/docs/development/issue-252.adoc @@ -26,20 +26,16 @@ can actually mean one of the following: * more generally `/foo.` * `/foo/index.` -where extension -is one of the following: `html, htm, shtml, phtml, php, asp, aspx, xml` +where the extension is one of the following: `html, htm, shtml, phtml, php, asp, aspx, xml` === Proposed Approach -* Define a proper name for the "link without extension" -(`prefixOnlyHref`) -* When checking local resources, add a special case -for URLs with `prefixOnlyHref`. +* Define a proper name for the "link without extension" (`prefixOnlyHref`) +* When checking local resources, add a special case for URLs with `prefixOnlyHref`. -* Add a new configuration item with the extensions to be checked, -the default should be the list given above -(`ITEM_NAME_prefixOnlyHrefExtensions`) +* Add a new configuration item with the extensions to be checked. +The default should be the list given above. * Add these defaults to `Web` @@ -50,6 +46,6 @@ the default should be the list given above **** -Document the decision in Detail by moving all information from this Discussion to capter 9 "Design Decisions" of your arc42 docs. +Document the decision in Detail by moving all information from this Discussion to chapter 9 "Design Decisions" of your arc42 docs. ****