From 60aa7bc9ec2df530e0b1c00430fdd06cecc2d3dc Mon Sep 17 00:00:00 2001 From: Gerd Aschemann Date: Wed, 18 Sep 2024 09:49:01 +0200 Subject: [PATCH] Avoid NPE in config initialization - Configuration had an NPE (which only occured in newer tests) - As Configuration::isValid threw an error on configuration errors, it was migrated to validate. - provide strong test coverage for Gradle task/plugin - Drop unused (and untested) main method from AllChecksRunner --- .../htmlsanitycheck/AllChecksRunner.java | 19 +---- .../aim42/htmlsanitycheck/Configuration.java | 29 +++---- .../htmlsanitycheck/ConfigurationSpec.groovy | 30 +++---- .../HtmlSanityCheckTask.groovy | 81 ++++++++----------- .../HtmlSanityCheckBaseSpec.groovy | 44 ++++++++++ .../HtmlSanityCheckPluginSpec.groovy | 38 +++++++++ ... HtmlSanityCheckTaskFunctionalSpec.groovy} | 74 +++++------------ .../HtmlSanityCheckTaskSpec.groovy | 64 +++++++++++++++ 8 files changed, 228 insertions(+), 151 deletions(-) create mode 100644 htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckBaseSpec.groovy create mode 100644 htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckPluginSpec.groovy rename htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/{HtmlSanityCheckTaskFunctionalTest.groovy => HtmlSanityCheckTaskFunctionalSpec.groovy} (61%) create mode 100644 htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskSpec.groovy diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/AllChecksRunner.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/AllChecksRunner.java index 744dd09a..7e726bde 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/AllChecksRunner.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/AllChecksRunner.java @@ -57,7 +57,6 @@ public class AllChecksRunner { /** * runs all available checks - * */ public AllChecksRunner(Configuration configuration) { @@ -75,12 +74,12 @@ public AllChecksRunner(Configuration configuration) { this.checkingResultsDir = configuration.getCheckingResultsDir(); this.junitResultsDir = configuration.getJunitResultsDir(); - logger.debug("AllChecksRunner created with " + this.checkers.size() + " checkers for " + filesToCheck.size() + " files"); + logger.debug("AllChecksRunner created with {} checkers for {} files", + this.checkers.size(), filesToCheck.size()); } /** * Performs all available checks on pageToCheck - * */ public PerRunResults performAllChecks() throws IOException { @@ -110,9 +109,9 @@ public PerRunResults performAllChecks() throws IOException { } /** - * Performs all configured checks on a single HTML file. + * Performs all configured checks on a single HTML file. *

- * Creates a {@link org.aim42.htmlsanitycheck.collect.SinglePageResults} instance to keep checking results. + * Creates a {@link org.aim42.htmlsanitycheck.collect.SinglePageResults} instance to keep checking results. */ protected SinglePageResults performChecksForOneFile(File thisFile) throws IOException { @@ -179,14 +178,4 @@ private void reportCheckingResultsAsJUnitXml(String resultsDir) { Reporter reporter = new JUnitXmlReporter(resultsForAllPages, resultsDir); reporter.reportFindings(); } - - /** - * Runs the checks from the command - * line with default settings... - */ - public 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 - } } \ No newline at end of file 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 098bcd6c..772ff738 100644 --- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/Configuration.java +++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/Configuration.java @@ -46,8 +46,8 @@ public class Configuration { * 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. + * 1.) Set-added to httpSuccessCodes, + * 2.) Set-subtracted from the warnings and errors. */ // Make modifiable copies! final Set httpWarningCodes = new HashSet<>(Web.HTTP_WARNING_CODES); @@ -75,7 +75,7 @@ public synchronized void setSourceConfiguration(final File sourceDir, final Set< } /** - * overwrites httpSuccessCodes configuration + * Overrides httpSuccessCodes configuration */ public void overrideHttpSuccessCodes(Set additionalSuccessCodes) { if (null != additionalSuccessCodes) { @@ -86,12 +86,12 @@ public void overrideHttpSuccessCodes(Set additionalSuccessCodes) { } ); } else { - log.warn("Trying to override http success codes with empty set of codes"); + log.warn("Trying to override http success codes with an empty set of codes"); } } /** - * overwrites httpWarningCodes configuration + * Overrides httpWarningCodes configuration */ public void overrideHttpWarningCodes(Set additionalWarningCodes) { if (null != additionalWarningCodes) { @@ -102,12 +102,12 @@ public void overrideHttpWarningCodes(Set additionalWarningCodes) { } ); } else { - log.warn("Trying to override http warning codes with empty set of codes"); + log.warn("Trying to override http warning codes with an empty set of codes"); } } /** - * overwrites httpErrorCodes configuration + * Overrides httpErrorCodes configuration */ public void overrideHttpErrorCodes(Set additionalErrorCodes) { if (null != additionalErrorCodes) { @@ -118,17 +118,17 @@ public void overrideHttpErrorCodes(Set additionalErrorCodes) { } ); } else { - log.warn("Trying to override http error codes with empty set of codes"); + log.warn("Trying to override http error codes with an empty set of codes"); } } /** - * checks plausibility of configuration: - * We need at least one html file as input, maybe several + * Checks plausibility of configuration: + * We need at least one HTML file as input, maybe several */ - public Boolean isValid() throws MisconfigurationException { + public void validate() throws MisconfigurationException { - // cannot check if source director is null (= unspecified) + // cannot check if the source directory is null (= unspecified) if ((sourceDir == null)) { throw new MisconfigurationException("source directory must not be null"); } @@ -154,10 +154,5 @@ public Boolean isValid() throws MisconfigurationException { if (checksToExecute == null || checksToExecute.isEmpty()) { throw new MisconfigurationException("checks to execute have to be a non-empty list"); } - - - // if no exception has been thrown until now, - // the configuration seems to be valid.. - return true; } } 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 7296d5bb..f1c4af0b 100644 --- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/ConfigurationSpec.groovy +++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/ConfigurationSpec.groovy @@ -37,7 +37,6 @@ class ConfigurationSpec extends Specification { and: "503 is NOT contained in warningCodes" !myConfig.getHttpWarningCodes().contains(newSuccessCode) - } def "can overwrite http warning codes"() { @@ -88,8 +87,7 @@ class ConfigurationSpec extends Specification { when: "we create a configuration with this single file" myConfig.setSourceConfiguration(tempDir, [htmlFile] as Set) - - myConfig.isValid() + myConfig.validate() then: htmlFile.exists() @@ -111,29 +109,26 @@ class ConfigurationSpec extends Specification { myConfig.setSourceConfiguration(srcDir, srcDocs as Set) when: "configuration is validated..." - myConfig.isValid() + myConfig.validate() then: "an exception is thrown" thrown MisconfigurationException - where: - - srcDir | srcDocs - null | null + srcDir | srcDocs + null | null new File("/_non/exists_/d_ir/") | null new File("/_non/exists_/d_ir/") | [] // existing but empty directory is absurd too... - File.createTempDir() | [] - + File.createTempDir() | [] } // this spec is a syntactic variation of the data (table-)driven test def "empty configuration makes no sense"() { when: - myConfig.isValid() + myConfig.validate() then: thrown MisconfigurationException @@ -151,14 +146,21 @@ class ConfigurationSpec extends Specification { .build() when: - myConfig.valid + myConfig.validate() then: def e = thrown(MisconfigurationException) e.message == "checks to execute have to be a non-empty list" where: - checkersToExecute << [[] as List] + checkersToExecute << [[] as List>] } -} + // The following methods only increase code coverage without providing any test at all + def "cannot overwrite http error codes with null list"() { + expect: "we overwrite the standard Configurations with null" + myConfig.overrideHttpSuccessCodes(null) + myConfig.overrideHttpWarningCodes(null) + myConfig.overrideHttpErrorCodes(null) + } +} \ 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 0c5938ae..536030b5 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 @@ -23,7 +23,6 @@ import org.gradle.api.tasks.TaskAction */ class HtmlSanityCheckTask extends DefaultTask { - // // we support checking several named files @InputFiles FileCollection sourceDocuments @@ -79,12 +78,8 @@ class HtmlSanityCheckTask extends DefaultTask { // private stuff // ************************************************************************** - - private Set allFilesToCheck - private Configuration myConfig - /** * Sets sensible defaults for important attributes. * @@ -92,16 +87,13 @@ class HtmlSanityCheckTask extends DefaultTask { * by setting outputs.upToDateWhen to false. */ HtmlSanityCheckTask() { - // Never consider this task up-to-date. // thx https://github.com/stevesaliman/gradle-cobertura-plugin/commit/d61191f7d5f4e8e89abcd5f3839a210985526648 outputs.upToDateWhen { false } // give sensible default for output directory, see https://github.com/aim42/htmlSanityCheck/issues/205 - checkingResultsDir = new File(project.buildDir, '/reports/htmlSanityCheck/') - junitResultsDir = new File(project.buildDir, '/test-results/htmlSanityCheck/') - - + checkingResultsDir = new File(project.DEFAULT_BUILD_DIR_NAME, '/reports/htmlSanityCheck/') + junitResultsDir = new File(project.DEFAULT_BUILD_DIR_NAME, '/test-results/htmlSanityCheck/') } void setSourceDir(File sourceDir) { @@ -112,13 +104,12 @@ class HtmlSanityCheckTask extends DefaultTask { } } -/** - * entry point for several html sanity checks - * @author Gernot Starke - */ + /** + * Entry point for several html sanity checks + * @author Gernot Starke + */ @TaskAction void sanityCheckHtml() { - // tell us about these parameters logBuildParameter() @@ -126,48 +117,43 @@ class HtmlSanityCheckTask extends DefaultTask { myConfig = setupConfiguration() // if we have no valid configuration, abort with exception - if (myConfig.isValid()) { - - // create output directory for checking results - checkingResultsDir.mkdirs() - assert checkingResultsDir.isDirectory() - assert checkingResultsDir.canWrite() - if (junitResultsDir) { - junitResultsDir.mkdirs() - assert junitResultsDir.isDirectory() - assert junitResultsDir.canWrite() - } + myConfig.validate() + + // create output directory for checking results + checkingResultsDir.mkdirs() + assert checkingResultsDir.isDirectory() + assert checkingResultsDir.canWrite() + if (junitResultsDir) { + junitResultsDir.mkdirs() + assert junitResultsDir.isDirectory() + assert junitResultsDir.canWrite() + } - // TODO: unclear: do we need to adjust pathnames if running on Windows(tm)?? + // TODO: unclear: do we need to adjust path-names if running on Windows(tm)?? - logger.info("buildfile-info", sourceDocuments?.toString()) - logger.info("allFilesToCheck" + allFilesToCheck.toString(), "") + logger.info("Source documents: '{}'", sourceDocuments) - // create an AllChecksRunner... - def allChecksRunner = new AllChecksRunner(myConfig) + // create an AllChecksRunner... + def allChecksRunner = new AllChecksRunner(myConfig) - // ... and perform the actual checks - def allChecks = allChecksRunner.performAllChecks() + // ... and perform the actual checks + def allChecks = allChecksRunner.performAllChecks() - // check for findings and fail build if requested - def nrOfFindingsOnAllPages = allChecks.nrOfFindingsOnAllPages() - logger.debug("Found ${nrOfFindingsOnAllPages} error(s) on all checked pages") + // check for findings and fail build if requested + def nrOfFindingsOnAllPages = allChecks.nrOfFindingsOnAllPages() + logger.debug("Found ${nrOfFindingsOnAllPages} error(s) on all checked pages") - if (failOnErrors && nrOfFindingsOnAllPages > 0) { - def failureMsg = """ + if (failOnErrors && nrOfFindingsOnAllPages > 0) { + def failureMsg = """ Your build configuration included 'failOnErrors=true', and ${nrOfFindingsOnAllPages} error(s) were found on all checked pages. See ${checkingResultsDir} for a detailed report.""" - throw new GradleException(failureMsg) - } - } else { - logger.warn("""Fatal configuration errors preventing checks:\n - ${myConfig.toString()}""") + throw new GradleException(failureMsg) } } /** * setup a @Configuration instance containing all given configuration parameters - * from the gradle buildfile. + * from the gradle build-file. * * This method has to be updated in case of new configuration parameters!! * @@ -177,7 +163,7 @@ See ${checkingResultsDir} for a detailed report.""" protected Configuration setupConfiguration() { Configuration result = Configuration.builder() - .sourceDocuments(sourceDocuments.files) + .sourceDocuments(sourceDocuments?.files) .sourceDir(sourceDir) .checkingResultsDir(checkingResultsDir) .junitResultsDir(junitResultsDir) @@ -210,16 +196,13 @@ See ${checkingResultsDir} for a detailed report.""" private void logBuildParameter() { logger.info "=" * 70 - logger.info "Parameters given to sanityCheck plugin from gradle buildfile..." + logger.info "Parameters given to sanityCheck plugin from gradle build-file..." logger.info "Files to check : $sourceDocuments" logger.info "Source directory: $sourceDir" logger.info "Results dir : $checkingResultsDir" logger.info "JUnit dir : $junitResultsDir" logger.info "Fail on errors : $failOnErrors" - } - - } /*======================================================================== diff --git a/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckBaseSpec.groovy b/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckBaseSpec.groovy new file mode 100644 index 00000000..0fee6a8d --- /dev/null +++ b/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckBaseSpec.groovy @@ -0,0 +1,44 @@ +package org.aim42.htmlsanitycheck + +import org.junit.Rule +import org.junit.rules.TemporaryFolder +import spock.lang.Specification + +class HtmlSanityCheckBaseSpec extends Specification { + final static VALID_HTML = """""" + final static INVALID_HTML = """ """ + + @Rule + TemporaryFolder testProjectDir = new TemporaryFolder() + File sourceDir + File buildDir + File buildFile + File htmlFile + + def setup() { + buildDir = testProjectDir.newFolder("build") + sourceDir = testProjectDir.newFolder("src") + sourceDir.mkdirs() + htmlFile = new File (sourceDir, "test.html") + } + + protected void createBuildFile(String extendedTaskConfig = "") { + // a note on writing paths to the build script on windows: + // - the default file separator is a backslash + // - as the path is written into a quoted string, backslashes should be quoted + // - to avoid string manipulation or similar, we use URIs to avoid the problem + // (URIs consist of / instead of backslashes) + buildFile = testProjectDir.newFile('build.gradle') << """ + plugins { + id 'org.aim42.htmlSanityCheck' + } + + htmlSanityCheck { + sourceDir = file ("src") + checkingResultsDir = file ("build") + + ${extendedTaskConfig} + } + """.stripIndent() + } +} \ No newline at end of file diff --git a/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckPluginSpec.groovy b/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckPluginSpec.groovy new file mode 100644 index 00000000..eac07353 --- /dev/null +++ b/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckPluginSpec.groovy @@ -0,0 +1,38 @@ +package org.aim42.htmlsanitycheck + +import org.gradle.api.Project +import org.gradle.language.base.plugins.LifecycleBasePlugin +import org.gradle.testfixtures.ProjectBuilder +import spock.lang.Specification + +class HtmlSanityCheckPluginSpec extends Specification { + + def "plugin adds an htmlSanityCheck task to the project"() { + given: "a project" + Project project = ProjectBuilder.builder().build() + + when: "the plugin is applied" + project.plugins.apply HtmlSanityCheckPlugin + + then: "the htmlSanityCheck task is added" + project.tasks.named(HtmlSanityCheckPlugin.HTML_SANITY_CHECK) != null + } + + def "htmlSanityCheck task has correct type and properties"() { + given: "a project with the plugin applied" + Project project = ProjectBuilder.builder().build() + project.plugins.apply(HtmlSanityCheckPlugin) + + when: "retrieving the htmlSanityCheck task" + def task = project.tasks.named(HtmlSanityCheckPlugin.HTML_SANITY_CHECK).get() + + then: "the task is of type HtmlSanityCheckTask" + task instanceof HtmlSanityCheckTask + + and: "the task has the correct description" + task.description == 'performs semantic checks on html files' + + and: "the task is in the verification group" + task.group == LifecycleBasePlugin.VERIFICATION_GROUP + } +} \ No newline at end of file diff --git a/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskFunctionalTest.groovy b/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskFunctionalSpec.groovy similarity index 61% rename from htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskFunctionalTest.groovy rename to htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskFunctionalSpec.groovy index 631558ba..41146c68 100644 --- a/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskFunctionalTest.groovy +++ b/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskFunctionalSpec.groovy @@ -1,59 +1,29 @@ package org.aim42.htmlsanitycheck + import org.gradle.testkit.runner.GradleRunner import org.jsoup.Jsoup import org.jsoup.nodes.Element -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import spock.lang.Specification import spock.lang.Unroll import static org.gradle.testkit.runner.TaskOutcome.FAILED import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -class HtmlSanityCheckTaskFunctionalTest extends Specification { - private final static VALID_HTML = """""" - private final static INVALID_HTML = """ """ +class HtmlSanityCheckTaskFunctionalSpec extends HtmlSanityCheckBaseSpec { private final static GRADLE_VERSIONS = [ // 6.x or older does not work! - '7.6.3', // latest 7.x - '8.0.2', '8.1.1', '8.2.1', '8.3', '8.4', + '7.6.3', // latest 7.x + '8.0.2', '8.1.1', '8.2.1', '8.3', '8.4', '8.5', '8.6', '8.7', '8.8', '8.9', - '8.10', '8.10.1' // all 8.x (latest patches) - ] - - @Rule - TemporaryFolder testProjectDir = new TemporaryFolder() - File buildDir - File buildFile - File htmlFile - - def setup() { - buildDir = testProjectDir.newFolder("build") - htmlFile = testProjectDir.newFile("test.html") - // a note on writing paths to the build script on windows: - // - the default file separator is a backslash - // - as the path is written into a quoted string, backslashes should be quoted - // - to avoid string manipulation or similar, we use URIs to avoid the problem - // (URIs consist of / instead of backslashes) - buildFile = testProjectDir.newFile('build.gradle') << """ - plugins { - id 'org.aim42.htmlSanityCheck' - } - - htmlSanityCheck { - sourceDir = file( "${htmlFile.parentFile.toURI().path}" ) - checkingResultsDir = file( "${buildDir.toURI().path}" ) - } - """ - } + '8.10.1' // all 8.x (latest patches) + ] @Unroll def "can execute htmlSanityCheck task with Gradle version #gradleVersion"() { given: htmlFile << VALID_HTML + createBuildFile() when: - def result = runnerForHtmlSanityCheckTask(gradleVersion).build() then: @@ -67,11 +37,9 @@ class HtmlSanityCheckTaskFunctionalTest extends Specification { def "invalid HTML fails build with failOnErrors=true and Gradle version #gradleVersion"() { given: htmlFile << INVALID_HTML - buildFile << """ - htmlSanityCheck { + createBuildFile(""" failOnErrors = true - } - """ + """) when: @@ -90,14 +58,12 @@ class HtmlSanityCheckTaskFunctionalTest extends Specification { given: htmlFile << VALID_HTML testProjectDir.newFile("test-invalid.html") << INVALID_HTML - buildFile << """ - htmlSanityCheck { + createBuildFile(""" sourceDocuments = fileTree(sourceDir) { include '**/$htmlFile.name' } failOnErrors = true - } - """ + """) when: def result = runnerForHtmlSanityCheckTask(gradleVersion).build() @@ -113,13 +79,9 @@ class HtmlSanityCheckTaskFunctionalTest extends Specification { def "can select a subset of all checks to be performed with Gradle version #gradleVersion"() { given: htmlFile << VALID_HTML - buildFile << """ - import org.aim42.htmlsanitycheck.check.AllCheckers - - htmlSanityCheck { - checkerClasses = [AllCheckers.CHECKER_CLASSES.first()] - } - """ + createBuildFile(""" + checkerClasses = [org.aim42.htmlsanitycheck.check.AllCheckers.CHECKER_CLASSES.first()] + """) when: runnerForHtmlSanityCheckTask(gradleVersion).build() @@ -134,10 +96,10 @@ class HtmlSanityCheckTaskFunctionalTest extends Specification { private GradleRunner runnerForHtmlSanityCheckTask(String gradleVersion) { GradleRunner.create() - .withGradleVersion(gradleVersion) - .withProjectDir(testProjectDir.root) - .withPluginClasspath() - .withArguments('htmlSanityCheck') + .withGradleVersion(gradleVersion) + .withProjectDir(testProjectDir.root) + .withPluginClasspath() + .withArguments('htmlSanityCheck') } private static class HtmlReport { diff --git a/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskSpec.groovy b/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskSpec.groovy new file mode 100644 index 00000000..bae4f1bf --- /dev/null +++ b/htmlSanityCheck-gradle-plugin/src/test/groovy/org/aim42/htmlsanitycheck/HtmlSanityCheckTaskSpec.groovy @@ -0,0 +1,64 @@ +package org.aim42.htmlsanitycheck + +import org.gradle.api.GradleException +import org.gradle.api.Project +import org.gradle.testfixtures.ProjectBuilder + +class HtmlSanityCheckTaskSpec extends HtmlSanityCheckBaseSpec { + Project project + HtmlSanityCheckTask task + + def setup () { + project = ProjectBuilder.builder().withProjectDir(testProjectDir.root).build() + task = project.tasks.register(HtmlSanityCheckPlugin.HTML_SANITY_CHECK, HtmlSanityCheckTask).get() + } + + def "should initialize task with defaults"() { + expect: + task.failOnErrors == false + task.httpConnectionTimeout == 5000 + task.ignoreLocalHost == false + task.ignoreIPAddresses == false + task.checkingResultsDir == new File(project.DEFAULT_BUILD_DIR_NAME, '/reports/htmlSanityCheck/') + task.junitResultsDir == new File(project.DEFAULT_BUILD_DIR_NAME, '/test-results/htmlSanityCheck/') + } + + def "should work with simple file"() { + given: + htmlFile << VALID_HTML + task.setSourceDir(testProjectDir.root) + task.httpSuccessCodes = [299] + task.httpErrorCodes = [599] + task.httpWarningCodes = [199] + + when: + task.sanityCheckHtml() + + then: + task.sourceDocuments != null + } + + def "should throw exception if configuration is invalid"() { + when: + task.sanityCheckHtml() + + then: + def e = thrown(MisconfigurationException) + e.message.contains("source directory must not be null") + } + + def "should fail on invalid HTML with failOnErrors"() { + given: + htmlFile << INVALID_HTML + task.failOnErrors = true + task.setSourceDir(testProjectDir.root) + + when: + task.sanityCheckHtml() + + then: + def e = thrown(GradleException) + e.message.contains("Your build configuration included 'failOnErrors=true', and 1 error(s) were found on all checked pages.") + } + +} \ No newline at end of file