From 2a366b8e79141b5d0e8a67aeb69ef187a05fdc32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Schalk=20W=2E=20Cronj=C3=A9?= Date: Thu, 19 Jul 2018 10:26:55 +0200 Subject: [PATCH] More unittests for AsciidoctorCompatibilityTask (#240) --- README.adoc | 4 +- .../compat/AsciidoctorFunctionalSpec.groovy | 418 ++++++++--- .../AsciidoctorCompatibilityTask.groovy | 160 +---- .../gradle/compat/AsciidoctorTaskSpec.groovy | 660 ++---------------- 4 files changed, 409 insertions(+), 833 deletions(-) diff --git a/README.adoc b/README.adoc index 7e4f35473..e004ea2f2 100644 --- a/README.adoc +++ b/README.adoc @@ -588,9 +588,7 @@ options:: a Map specifying different options that can be sent to Asciidoctor. attributes:: a Map specifying various document attributes that can be sent to Asciidoctor Use `attributes` to append, Use `setAttributes` or `attributes=` to overwrite. -//// -To see examples of many of these configuration options used in practice, refer to the http://asciidoctor.github.io/asciidoctor-gradle-examples[Asciidoctor Gradle Examples] project. -//// +NOTE: Even though the DSL remains the same with this task, the internals have been changed to use the same `JAVA_EXEC` mechanism of the `org.asciidoctor.jvm.convert` plugins. The problems which the 1.5.x series suffered with classpaths anions disappearing shuol dnow be a thing of the past. == Kindlegen plugin diff --git a/asciidoctor-gradle-jvm/src/intTest/groovy/org/asciidoctor/gradle/compat/AsciidoctorFunctionalSpec.groovy b/asciidoctor-gradle-jvm/src/intTest/groovy/org/asciidoctor/gradle/compat/AsciidoctorFunctionalSpec.groovy index c0732a6ef..6ce2ef02d 100755 --- a/asciidoctor-gradle-jvm/src/intTest/groovy/org/asciidoctor/gradle/compat/AsciidoctorFunctionalSpec.groovy +++ b/asciidoctor-gradle-jvm/src/intTest/groovy/org/asciidoctor/gradle/compat/AsciidoctorFunctionalSpec.groovy @@ -17,6 +17,7 @@ package org.asciidoctor.gradle.compat import org.apache.commons.io.FileUtils import org.asciidoctor.gradle.internal.FunctionalSpecification +import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner import org.gradle.testkit.runner.TaskOutcome import spock.lang.IgnoreIf @@ -26,125 +27,376 @@ import spock.lang.IgnoreIf * * @author Peter Ledbrook */ -@SuppressWarnings(['DuplicateStringLiteral', 'MethodName', 'UnnecessaryGString']) +@SuppressWarnings(['DuplicateStringLiteral', 'MethodName']) class AsciidoctorFunctionalSpec extends FunctionalSpecification { static final String TEST_PROJECTS_DIR = FunctionalSpecification.TEST_PROJECTS_DIR + static final String ASCIIDOCTOR_TASK = 'asciidoctor' + static final String ASCIIDOCTOR_PATH = ':asciidoctor' + static final String ASCIIDOC_SAMPLE_FILE = 'sample.asciidoc' - @SuppressWarnings('MethodName') - @IgnoreIf({ System.getProperty('OFFLINE_MODE') }) - def "Should do nothing with an empty project"() { + File buildDir + + void setup() { + createTestProject('normal') + buildDir = new File(testProjectDir.root, 'build') + } + + void 'Should do nothing with an empty project'() { given: "A minimal build file" - def buildFile = testProjectDir.newFile("build.gradle") - buildFile << """\ - plugins { - id "org.asciidoctor.convert" - } - """ + getBuildFile('') when: - final result = GradleRunner.create() - .withProjectDir(testProjectDir.root) - .withArguments("asciidoctor") - .withPluginClasspath(pluginClasspath) - .build() + BuildResult result = runGradle() then: - result.task(":asciidoctor").outcome == TaskOutcome.NO_SOURCE + result.task(ASCIIDOCTOR_PATH).outcome == TaskOutcome.NO_SOURCE } - @SuppressWarnings('MethodName') - @IgnoreIf({ System.getProperty('OFFLINE_MODE') }) void 'Should build normally for a standard project'() { - given: "A minimal build file" - def buildFile = testProjectDir.newFile("build.gradle") - buildFile << """ - plugins { - id "org.asciidoctor.convert" - } - """ - - and: "Some source files" - FileUtils.copyDirectory(new File(TEST_PROJECTS_DIR, "normal"), testProjectDir.root) - final buildDir = new File(testProjectDir.root, "build") + given: 'A minimal build file' + getBuildFile('') when: - final result = GradleRunner.create() - .withProjectDir(testProjectDir.root) - .withArguments("asciidoctor") - .withPluginClasspath(pluginClasspath) - .build() + BuildResult result = runGradle() then: - result.task(":asciidoctor").outcome == TaskOutcome.SUCCESS + result.task(ASCIIDOCTOR_PATH).outcome == TaskOutcome.SUCCESS new File(buildDir, "asciidoc/html5/sample.html").exists() new File(buildDir, "asciidoc/html5/subdir/sample2.html").exists() } - @SuppressWarnings('MethodName') - @IgnoreIf({ System.getProperty('OFFLINE_MODE') }) - def "Task should be up-to-date when executed a second time"() { - given: "A minimal build file" - def buildFile = testProjectDir.newFile("build.gradle") - buildFile << """\ - plugins { - id "org.asciidoctor.convert" - } - """ - - and: "Some source files" - FileUtils.copyDirectory(new File(TEST_PROJECTS_DIR, "normal"), testProjectDir.root) + void 'Task should be up-to-date when executed a second time'() { + given: 'A minimal build file' + getBuildFile('') when: - GradleRunner.create() - .withProjectDir(testProjectDir.root) - .withArguments("asciidoctor") - .withPluginClasspath(pluginClasspath) - .build() - final result = GradleRunner.create() - .withProjectDir(testProjectDir.root) - .withArguments("asciidoctor") - .withPluginClasspath(pluginClasspath) - .build() + runGradle() + BuildResult result = runGradle() then: - result.task(":asciidoctor").outcome == TaskOutcome.UP_TO_DATE + result.task(ASCIIDOCTOR_PATH).outcome == TaskOutcome.UP_TO_DATE } - @SuppressWarnings('MethodName') - @IgnoreIf({ System.getProperty('OFFLINE_MODE') }) - def "Task should not be up-to-date when classpath is changed"() { - given: "A minimal build file" - def buildFile = testProjectDir.newFile("build.gradle") - buildFile << """\ - plugins { - id "org.asciidoctor.convert" - } + void 'Task should not be up-to-date when classpath is changed'() { + given: 'A minimal build file' + getBuildFile(''' if (project.hasProperty('modifyClasspath')) { dependencies { - asciidoctor 'org.hibernate.infra:hibernate-asciidoctor-extensions:1.0.3.Final' + asciidoctor 'org.jsoup:jsoup:1.11.2' } } - """ + ''') + + + when: + runGradle() + BuildResult result = getGradleRunner([ASCIIDOCTOR_TASK,'-PmodifyClasspath']).build() + + then: + result.task(ASCIIDOCTOR_PATH).outcome == TaskOutcome.SUCCESS + } + + void 'Should build normally for a standard project with multiple backends'() { + given: 'A minimal build file' + getBuildFile(''' + asciidoctor { + backends 'html5', 'docbook' + } + ''') + + when: + BuildResult result = runGradle() + + then: + result.task(ASCIIDOCTOR_PATH).outcome == TaskOutcome.SUCCESS + new File(buildDir, 'asciidoc/html5/sample.html').exists() + new File(buildDir, 'asciidoc/html5/subdir/sample2.html').exists() + new File(buildDir, 'asciidoc/docbook/sample.xml').exists() + new File(buildDir, 'ascidoc/docbook/subdir/sample2.xml').exists() + } + + + void 'Processes a single document given a value for sourceDocumentName'() { - and: "Some source files" - FileUtils.copyDirectory(new File(TEST_PROJECTS_DIR, "normal"), testProjectDir.root) + given: + getBuildFile(""" + asciidoctor { + sources { + include '${ASCIIDOC_SAMPLE_FILE}' + } + } + """) when: - GradleRunner.create() - .withProjectDir(testProjectDir.root) - .withArguments("asciidoctor") - .withPluginClasspath(pluginClasspath) - .build() - final result = GradleRunner.create() - .withProjectDir(testProjectDir.root) - .withArguments("asciidoctor", "-PmodifyClasspath") - .withPluginClasspath(pluginClasspath) - .build() + runGradle() then: - result.task(":asciidoctor").outcome == TaskOutcome.SUCCESS + new File(buildDir, 'asciidoc/html5/sample.html').exists() + !new File(buildDir, 'asciidoc/html5/subdir/sample2.html').exists() + } + + File getBuildFile(final String extraContent = '') { + getJvmConvertBuildFile(""" + asciidoctorj.noDefaultRepositories = true + + ${extraContent} + """, + 'org.asciidoctor.convert' + ) } + BuildResult runGradle( List args = ['asciidoctor']) { + getGradleRunner(args).build() + } } + +// @SuppressWarnings('MethodName') +// def "Setting baseDir results in the correct value being sent to Asciidoctor"() { +// given: +// File basedir = new File(testRootDir, 'my_base_dir') +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// resourceCopyProxy = mockCopyProxy +// sourceDir = srcDir +// outputDir = outDir +// baseDir = basedir +// } +// when: +// task.processAsciidocSources() +// then: +// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { +// it.base_dir == basedir.absolutePath +// }) +// } +// +// @SuppressWarnings('MethodName') +// def "Omitting a value for baseDir results in sending the dir of the processed file"() { +// given: +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// asciidoctor = mockAsciidoctor +// resourceCopyProxy = mockCopyProxy +// sourceDir = srcDir +// outputDir = outDir +// } +// when: +// task.processAsciidocSources() +// then: +// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), +// { it.base_dir == new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE).parentFile.absolutePath }) +// } +// +// @SuppressWarnings('MethodName') +// def "Setting baseDir to null results in no value being sent to Asciidoctor"() { +// given: +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// resourceCopyProxy = mockCopyProxy +// sourceDir = srcDir +// outputDir = outDir +// baseDir = null +// } +// when: +// task.processAsciidocSources() +// then: +// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { !it.base_dir }) +// } +// +// @SuppressWarnings('MethodName') +// def "Safe mode option is equal to level of SafeMode.UNSAFE by default"() { +// given: +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// resourceCopyProxy = mockCopyProxy +// sourceDir = srcDir +// outputDir = outDir +// } +// when: +// task.processAsciidocSources() +// then: +// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { +// it.safe == SafeMode.UNSAFE.level +// }) +// } +// +// @SuppressWarnings('MethodName') +// def "Safe mode configuration option as integer is honored"() { +// given: +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// resourceCopyProxy = mockCopyProxy +// sourceDir = srcDir +// outputDir = outDir +// options = [ +// safe: SafeMode.SERVER.level +// ] +// } +// when: +// task.processAsciidocSources() +// then: +// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { +// it.safe == SafeMode.SERVER.level +// }) +// } +// +// @SuppressWarnings('MethodName') +// def "Safe mode configuration option as string is honored"() { +// given: +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// resourceCopyProxy = mockCopyProxy +// sourceDir = srcDir +// outputDir = outDir +// options = [ +// safe: 'server' +// ] +// } +// when: +// task.processAsciidocSources() +// then: +// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { +// it.safe == SafeMode.SERVER.level +// }) +// } +// +// @SuppressWarnings('MethodName') +// def "Safe mode configuration option as enum is honored"() { +// given: +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// resourceCopyProxy = mockCopyProxy +// sourceDir = srcDir +// outputDir = outDir +// options = [ +// safe: SafeMode.SERVER +// ] +// } +// when: +// task.processAsciidocSources() +// then: +// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { +// it.safe == SafeMode.SERVER.level +// }) +// } +// +// +// @SuppressWarnings('MethodName') +// def "Docinfo files are not copied to target directory"() { +// given: +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// asciidoctor = mockAsciidoctor +// resourceCopyProxy = mockCopyProxy +// sourceDir = srcDir +// outputDir = outDir +// } +// when: +// task.processAsciidocSources() +// then: +// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), _) +// !outDir.listFiles({ !it.directory && !(it.name =~ DOCINFO_FILE_PATTERN) } as FileFilter) +// } +// + +// @SuppressWarnings('MethodName') +// def "Should throw exception if the file sourceDocumentName starts with underscore"() { +// given: +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// resourceCopyProxy = mockCopyProxy +// sourceDir = srcDir +// outputDir = outDir +// sources { +// include ASCIIDOC_INVALID_FILE +// } +// } +// when: +// task.processAsciidocSources() +// then: +// 0 * mockAsciidoctor.renderFile(_, _) +// thrown(GradleException) +// } +// + +// def "When 'resources' not specified, then copy all images to backend"() { +// given: +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// resourceCopyProxy = mockCopyProxy +// +// sourceDir srcDir +// outputDir outDir +// backends AsciidoctorBackend.HTML5.id +// +// sources { +// include ASCIIDOC_SAMPLE_FILE +// } +// +// } +// when: +// task.processAsciidocSources() +// then: +// 1 * mockCopyProxy.copy(_, _) +// } +// +// def "When 'resources' not specified and more than one backend, then copy all images to every backend"() { +// given: +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// resourceCopyProxy = mockCopyProxy +// +// sourceDir srcDir +// outputDir outDir +// backends AsciidoctorBackend.HTML5.id, AsciidoctorBackend.DOCBOOK.id +// +// sources { +// include ASCIIDOC_SAMPLE_FILE +// } +// +// } +// when: +// task.processAsciidocSources() +// then: +// 1 * mockCopyProxy.copy(new File(outDir, AsciidoctorBackend.HTML5.id), _) +// 1 * mockCopyProxy.copy(new File(outDir, AsciidoctorBackend.DOCBOOK.id), _) +// } +// +// def "When 'resources' are specified, then copy according to all patterns"() { +// given: +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// resourceCopyProxy = mockCopyProxy +// +// sourceDir srcDir +// outputDir outDir +// backends AsciidoctorBackend.HTML5.id, AsciidoctorBackend.DOCBOOK.id +// +// sources { +// include ASCIIDOC_SAMPLE_FILE +// } +// +// resources { +// from(sourceDir) { +// include 'images/**' +// } +// } +// } +// +// when: +// task.processAsciidocSources() +// then: +// 1 * mockCopyProxy.copy(new File(outDir, AsciidoctorBackend.HTML5.id), _) +// 1 * mockCopyProxy.copy(new File(outDir, AsciidoctorBackend.DOCBOOK.id), _) +// } +// +// def "set output dir to something else than the default"() { +// given: +// project.version = '1.0.0-SNAPSHOT' +// project.group = 'com.acme' +// +// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { +// asciidoctor = mockAsciidoctor +// resourceCopyProxy = mockCopyProxy +// sourceDir = srcDir +// } +// project.buildDir = '/tmp/testbuild/asciidoctor' +// +// when: +// task.processAsciidocSources() +// +// then: 'the html files must be in testbuild/asciidoctor ' +// task.outputDir.absolutePath.replace('\\', '/').contains('testbuild/asciidoctor') +// 2 * mockAsciidoctor.renderFile(_, { it.to_dir.startsWith(project.buildDir.absolutePath) }) +// } +// +// diff --git a/asciidoctor-gradle-jvm/src/main/groovy/org/asciidoctor/gradle/compat/AsciidoctorCompatibilityTask.groovy b/asciidoctor-gradle-jvm/src/main/groovy/org/asciidoctor/gradle/compat/AsciidoctorCompatibilityTask.groovy index 751ee8d56..de5928f10 100755 --- a/asciidoctor-gradle-jvm/src/main/groovy/org/asciidoctor/gradle/compat/AsciidoctorCompatibilityTask.groovy +++ b/asciidoctor-gradle-jvm/src/main/groovy/org/asciidoctor/gradle/compat/AsciidoctorCompatibilityTask.groovy @@ -60,35 +60,24 @@ import static org.ysb33r.grolifant.api.StringUtils.stringize @SuppressWarnings(['MethodCount', 'Instanceof']) @CompileStatic class AsciidoctorCompatibilityTask extends DefaultTask { -// private static final boolean IS_WINDOWS = System.getProperty('os.name').contains('Windows') private static final String PATH_SEPARATOR = OperatingSystem.current().pathSeparator -// private static final String DOUBLE_BACKLASH = '\\\\' -// private static final String BACKLASH = '\\' -// private static final String SAFE_MODE_CLASSNAME = 'org.asciidoctor.gradle.base.SafeMode' private static final String MIGRATE_GEMS_MSG = 'When upgrading GEMs, \'requires\' will need to be set via the asciidoctorj project and task extensions. Use setGemPaths method in extension(s) to set GEM paths.' private static final String DEFAULT_BACKEND = AsciidoctorBackend.HTML5.id -// public static final String ASCIIDOCTOR_FACTORY_CLASSNAME = 'org.asciidoctor.Asciidoctor$Factory' - private boolean baseDirSetToNull private Object outDir private Object srcDir private final List gemPaths = [] private final Set backends = [] private final Set requires = [] + private final Set migrationMessages = [] private final Map opts = [:] private final Map attrs = [:] private PatternSet sourceDocumentPattern private CopySpec resourceCopy -// private static ClassLoader cl private boolean separateOutputDirs = true -// private final static Map ASCIIDOCTORS = [:] -// private final static Lock EXEC_LOCK = new ReentrantLock() - - private final Set migrationMessages = [] - /** If set to true each backend will be output to a separate subfolder below {@code outputDir} * @since 1.5.1 */ @@ -675,89 +664,6 @@ class AsciidoctorCompatibilityTask extends DefaultTask { } as List } -// @SuppressWarnings('CatchException') -// @SuppressWarnings('DuplicateStringLiteral') -// protected void processDocumentsAndResources(final String backend) { -// try { -// resourceCopyProxy.copy(outputBackendDir(outputDir, backend), resourceCopySpec) -// -// sourceFileTree.files.each { File file -> -// if (file.name.startsWith('_')) { -// throw new InvalidUserDataException('Source documents may not start with an underscore') -// } -// File destinationParentDir = owner.outputDirFor(file, sourceDir.absolutePath, outputDir, backend) -// processSingleFile(backend, destinationParentDir, file) -// } -// -// } catch (Exception e) { -// throw new GradleException('Error running Asciidoctor', e) -// } -// } - -// protected void processSingleFile(String backend, File destinationParentDir, File file) { -// if (logDocuments) { -// logger.lifecycle("Converting $file") -// } -// asciidoctor.renderFile(file, mergedOptions(file, -// [ -// project : project, -// options : options, -// attributes: attrs, -// baseDir : !baseDir && !baseDirSetToNull ? file.parentFile : baseDir, -// projectDir: project.projectDir, -// rootDir : project.rootDir, -// outputDir : destinationParentDir, -// backend : backend])) -// } - -// @SuppressWarnings('AbcMetric') -// private static Map mergedOptions(File file, Map params) { -// Map mergedOptions = [:] -// mergedOptions.putAll(params.options) -// mergedOptions.backend = params.backend -// mergedOptions.in_place = false -// mergedOptions.safe = resolveSafeModeLevel(mergedOptions.safe, 0i) -// mergedOptions.to_dir = params.outputDir -// if (params.baseDir) { -// mergedOptions.base_dir = params.baseDir -// } -// -// if (mergedOptions.to_file) { -// File toFile = new File(mergedOptions.to_file) -// mergedOptions.to_file = new File(mergedOptions.remove('to_dir'), toFile.name) -// } -// -// Map attributes = [:] -// processMapAttributes(attributes, params.attributes) -// -// // Note: Directories passed as relative to work around issue #83 -// // Asciidoctor cannot handle absolute paths in Windows properly -// attributes.projectdir = AsciidoctorUtils.getRelativePath(params.projectDir, file.parentFile) -// attributes.rootdir = AsciidoctorUtils.getRelativePath(params.rootDir, file.parentFile) -// -// // resolve these properties here as we want to catch both Map and String definitions parsed above -// attributes.'project-name' = attributes.'project-name' ?: params.project.name -// attributes.'project-group' = attributes.'project-group' ?: (params.project.group ?: '') -// attributes.'project-version' = attributes.'project-version' ?: (params.project.version ?: '') -// mergedOptions.attributes = attributes -// -// // Issue #14 force GString -> String as jruby will fail -// // to find an exact match when invoking Asciidoctor -// for (entry in mergedOptions) { -// if (entry.value instanceof CharSequence) { -// mergedOptions[entry.key] = entry.value.toString() -// } else if (entry.value instanceof List) { -// mergedOptions[entry.key] = stringifyList(entry.value) -// } else if (entry.value instanceof Map) { -// mergedOptions[entry.key] = stringifyMap(entry.value) -// } else if (entry.value instanceof File) { -// mergedOptions[entry.key] = entry.value.absolutePath -// } -// } -// -// mergedOptions -// } - @CompileDynamic private static List stringifyList(List input) { input.collect { element -> @@ -794,22 +700,6 @@ class AsciidoctorCompatibilityTask extends DefaultTask { output } - protected static void processMapAttributes(Map attributes, Map rawAttributes) { - // copy all attributes in order to prevent changes down - // the Asciidoctor chain that could cause serialization - // problems with Gradle -> all inputs/outputs get serialized - // for caching purposes; Ruby objects are non-serializable - // Issue #14 force GString -> String as jruby will fail - // to find an exact match when invoking Asciidoctor - for (entry in rawAttributes) { - if (entry.value == null || entry.value instanceof Boolean) { - attributes[entry.key] = entry.value - } else { - attributes[entry.key] = entry.value.toString() - } - } - } - @CompileDynamic protected static void processCollectionAttributes(Map attributes, rawAttributes) { for (attr in rawAttributes) { @@ -868,53 +758,5 @@ class AsciidoctorCompatibilityTask extends DefaultTask { defaultLevel } } - -// static Class loadClass(String className) { -// cl.loadClass(className) -// } - -// @SuppressWarnings('AssignmentToStaticFieldFromInstanceMethod') -// private void setupClassLoader() { -// if (classpath?.files) { -// def urls = classpath.files.collect { it.toURI().toURL() } -// cl = new URLClassLoader(urls as URL[], Thread.currentThread().contextClassLoader) -// Thread.currentThread().contextClassLoader = cl -// } else { -// cl = Thread.currentThread().contextClassLoader -// } -// } - -// @SuppressWarnings('CatchException') -// private withAsciidoctor(Closure cl) { -// EXEC_LOCK.lock() -// try { -// def key = new AsciidoctorProxyCacheKey( -// classpath?.files?.toList(), -// asGemPath() -// ) -// def asciidoctor = ASCIIDOCTORS.computeIfAbsent(key) { k -> -// def clazz = loadClass(ASCIIDOCTOR_FACTORY_CLASSNAME) -// Class asciidoctorExtensionsDslRegistry = loadClass('org.asciidoctor.groovydsl.AsciidoctorExtensions') -// -// if (k.gemPath) { -// new AsciidoctorProxyImpl(delegate: clazz.create(k.gemPath), extensionRegistry: asciidoctorExtensionsDslRegistry.newInstance()) -// } else { -// try { -// new AsciidoctorProxyImpl(delegate: clazz.create(null as String), extensionRegistry: asciidoctorExtensionsDslRegistry.newInstance()) -// } catch (Exception e) { -// // Asciidoctor < 1.5.1 can't handle a null gemPath, so fallback to default create() method -// new AsciidoctorProxyImpl(delegate: clazz.create(), extensionRegistry: asciidoctorExtensionsDslRegistry.newInstance()) -// } -// } -// } -// cl.call(asciidoctor) -// } finally { -// if (asciidoctor) { -// asciidoctor.unregisterAllExtensions() -// } -// EXEC_LOCK.unlock() -// } -// } - } diff --git a/asciidoctor-gradle-jvm/src/test/groovy/org/asciidoctor/gradle/compat/AsciidoctorTaskSpec.groovy b/asciidoctor-gradle-jvm/src/test/groovy/org/asciidoctor/gradle/compat/AsciidoctorTaskSpec.groovy index c2e3278c0..e705e035d 100755 --- a/asciidoctor-gradle-jvm/src/test/groovy/org/asciidoctor/gradle/compat/AsciidoctorTaskSpec.groovy +++ b/asciidoctor-gradle-jvm/src/test/groovy/org/asciidoctor/gradle/compat/AsciidoctorTaskSpec.groovy @@ -16,10 +16,12 @@ package org.asciidoctor.gradle.compat import org.asciidoctor.gradle.AsciidoctorTask +import org.gradle.api.GradleException import org.gradle.api.Project import org.gradle.api.Task import org.gradle.testfixtures.ProjectBuilder import spock.lang.Specification +import spock.lang.Unroll /** * Asciidoctor task specification @@ -53,7 +55,6 @@ class AsciidoctorTaskSpec extends Specification { def setup() { project = ProjectBuilder.builder().withName('test').build() project.configurations.create(ASCIIDOCTOR) -// mockAsciidoctor = Mock(AsciidoctorProxy) mockCopyProxy = Mock(ResourceCopyProxy) testRootDir = new File('.') srcDir = new File(testRootDir, ASCIIDOC_RESOURCES_DIR).absoluteFile @@ -61,12 +62,10 @@ class AsciidoctorTaskSpec extends Specification { systemOut = new ByteArrayOutputStream() originSystemOut = System.out System.out = new PrintStream(systemOut) -// ASCIIDOCTORS.put(new AsciidoctorProxyCacheKey(gemPath: '', classpath: []), mockAsciidoctor) } def cleanup() { System.out = originSystemOut -// ASCIIDOCTORS.clear() } @SuppressWarnings('MethodName') @@ -432,590 +431,75 @@ class AsciidoctorTaskSpec extends Specification { task.inputs.files.contains(project.file("${imagesDir}/fake.txt")) } -//// @SuppressWarnings('DuplicateNumberLiteral') -//// void "Add asciidoctor task with multiple backends"() { -//// when: -//// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -//// resourceCopyProxy = mockCopyProxy -//// sourceDir = srcDir -//// outputDir = outDir -//// backends AsciidoctorBackend.DOCBOOK.id, AsciidoctorBackend.HTML5.id -//// } -//// -//// task.processAsciidocSources() -//// then: -//// 2 * mockAsciidoctor.renderFile(_, { Map map -> map.backend == AsciidoctorBackend.DOCBOOK.id }) -//// 2 * mockAsciidoctor.renderFile(_, { Map map -> map.backend == AsciidoctorBackend.HTML5.id }) -//// } -//// -//// @SuppressWarnings('MethodName') -//// @SuppressWarnings('DuplicateNumberLiteral') -//// def "Adds asciidoctor task with supported backend"() { -//// expect: -//// project.tasks.findByName(ASCIIDOCTOR) == null -//// when: -//// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -//// resourceCopyProxy = mockCopyProxy -//// sourceDir srcDir -//// outputDir = outDir -//// } -//// -//// task.processAsciidocSources() -//// then: -//// 2 * mockAsciidoctor.renderFile(_, { Map map -> map.backend == AsciidoctorBackend.HTML5.id }) -//// !systemOut.toString().contains('deprecated') -//// } -//// -//// @SuppressWarnings('MethodName') -//// @SuppressWarnings('DuplicateNumberLiteral') -//// def "Using setBackend should output a warning"() { -//// expect: -//// project.tasks.findByName(ASCIIDOCTOR) == null -//// when: -//// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -//// resourceCopyProxy = mockCopyProxy -//// sourceDir = srcDir -//// outputDir = outDir -//// backends AsciidoctorBackend.DOCBOOK.id -//// } -//// -//// task.processAsciidocSources() -//// then: -//// 2 * mockAsciidoctor.renderFile(_, { Map map -> map.backend == AsciidoctorBackend.DOCBOOK.id }) -//// } -//// -//// @SuppressWarnings('MethodName') -//// def "Adds asciidoctor task throws exception"() { -//// expect: -//// project.tasks.findByName(ASCIIDOCTOR) == null -//// when: -//// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -//// resourceCopyProxy = mockCopyProxy -//// sourceDir = srcDir -//// outputDir = outDir -//// } -//// -//// task.processAsciidocSources() -//// then: -//// mockAsciidoctor.renderFile(_, _) >> { throw new IllegalArgumentException() } -//// thrown(GradleException) -//// } -//// -//// @SuppressWarnings('MethodName') -//// def "Processes a single document given a value for sourceDocumentName"() { -//// when: -//// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -//// resourceCopyProxy = mockCopyProxy -//// sourceDir = srcDir -//// outputDir = outDir -//// sources { -//// include ASCIIDOC_SAMPLE_FILE -//// } -//// } -//// -//// task.processAsciidocSources() -//// then: -//// 1 * mockAsciidoctor.renderFile(_, _) -//// } -//// -//// @SuppressWarnings('MethodName') -//// def "Reuses asciidoctor instance for multiple tasks"() { -//// when: -//// (1..2).collect { -//// project.tasks.create(name: "asciidoctor$it", type: AsciidoctorTask) { -//// resourceCopyProxy = mockCopyProxy -//// sourceDir = srcDir -//// outputDir = new File(outDir, "dir$it") -//// sources { -//// include ASCIIDOC_SAMPLE_FILE -//// } -//// extensions {} -//// } -//// -//// }.each { -//// it.processAsciidocSources() -//// } -//// -//// then: -//// 2 * mockAsciidoctor.unregisterAllExtensions() -//// 2 * mockAsciidoctor.renderFile(_, _) -//// 2 * mockAsciidoctor.registerExtensions(_) -//// } -//// -//// @SuppressWarnings('MethodName') -//// def "Source documents in directories end up in the corresponding output directory"() { -//// given: -//// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -//// resourceCopyProxy = mockCopyProxy -//// sourceDir = srcDir -//// outputDir = outDir -//// separateOutputDirs = false -//// } -//// when: -//// task.processAsciidocSources() -//// then: -//// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE2_FILE), { -//// it.to_dir == new File(task.outputDir, 'subdir').absolutePath -//// }) -//// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { -//// it.to_dir == task.outputDir.absolutePath -//// }) -//// and: -//// 0 * mockAsciidoctor.renderFile(_, _) -//// } -//// -//// @SuppressWarnings('MethodName') -//// def "Should support String value for attributes option"() { -//// given: -//// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -//// resourceCopyProxy = mockCopyProxy -//// sourceDir = srcDir -//// outputDir = outDir -//// sources { -//// include ASCIIDOC_SAMPLE_FILE -//// } -//// options = [ -//// attributes: 'toc=right source-highlighter=coderay' -//// ] -//// } -//// when: -//// task.processAsciidocSources() -//// then: -//// 1 * mockAsciidoctor.renderFile(_, _) -//// } -//// -//// @SuppressWarnings('MethodName') -//// @SuppressWarnings('DuplicateStringLiteral') -//// def "Should support GString value for attributes option"() { -//// given: -//// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -//// resourceCopyProxy = mockCopyProxy -//// sourceDir = srcDir -//// outputDir = outDir -//// sources { -//// include ASCIIDOC_SAMPLE_FILE -//// } -//// def attrs = 'toc=right source-highlighter=coderay' -//// options = [ -//// attributes: "$attrs" -//// ] -//// } -//// when: -//// task.processAsciidocSources() -//// then: -//// 1 * mockAsciidoctor.renderFile(_, _) -//// } -//// -//// @SuppressWarnings('MethodName') -//// @SuppressWarnings('DuplicateStringLiteral') -//// def "Should support List value for attributes option"() { -//// given: -//// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -//// asciidoctor = mockAsciidoctor -//// resourceCopyProxy = mockCopyProxy -//// sourceDir = srcDir -//// outputDir = outDir -//// sources { -//// include ASCIIDOC_SAMPLE_FILE -//// } -//// def highlighter = 'coderay' -//// options = [ -//// attributes: ['toc=right', "source-highlighter=$highlighter"] -//// ] -//// } -//// when: -//// task.processAsciidocSources() -//// then: -//// 1 * mockAsciidoctor.renderFile(_, _) -//// } -//// -// @SuppressWarnings('MethodName') -// def "Throws exception when attributes embedded in options is an unsupported type"() { -// when: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// sources { -// include ASCIIDOC_SAMPLE_FILE -// } -// options = [ -// attributes: 23 -// ] -// } -// task.processAsciidocSources() -// then: -// thrown(InvalidUserDataException) -// } - -// @SuppressWarnings('MethodName') -// def "Setting baseDir results in the correct value being sent to Asciidoctor"() { -// given: -// File basedir = new File(testRootDir, 'my_base_dir') -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// baseDir = basedir -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { -// it.base_dir == basedir.absolutePath -// }) -// } -// -// @SuppressWarnings('MethodName') -// def "Omitting a value for baseDir results in sending the dir of the processed file"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// asciidoctor = mockAsciidoctor -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), -// { it.base_dir == new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE).parentFile.absolutePath }) -// } -// -// @SuppressWarnings('MethodName') -// def "Setting baseDir to null results in no value being sent to Asciidoctor"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// baseDir = null -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { !it.base_dir }) -// } -// -// @SuppressWarnings('MethodName') -// def "Safe mode option is equal to level of SafeMode.UNSAFE by default"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { -// it.safe == SafeMode.UNSAFE.level -// }) -// } -// -// @SuppressWarnings('MethodName') -// def "Safe mode configuration option as integer is honored"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// options = [ -// safe: SafeMode.SERVER.level -// ] -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { -// it.safe == SafeMode.SERVER.level -// }) -// } -// -// @SuppressWarnings('MethodName') -// def "Safe mode configuration option as string is honored"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// options = [ -// safe: 'server' -// ] -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { -// it.safe == SafeMode.SERVER.level -// }) -// } -// -// @SuppressWarnings('MethodName') -// def "Safe mode configuration option as enum is honored"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// options = [ -// safe: SafeMode.SERVER -// ] -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { -// it.safe == SafeMode.SERVER.level -// }) -// } -// -// @SuppressWarnings('MethodName') -// def "Attributes projectdir and rootdir are always set to relative dirs of the processed file"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { -// it.attributes.projectdir == AsciidoctorUtils.getRelativePath(project.projectDir, new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE).parentFile) -// it.attributes.rootdir == AsciidoctorUtils.getRelativePath(project.rootDir, new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE).parentFile) -// }) -// } -// -// @SuppressWarnings('MethodName') -// def "Docinfo files are not copied to target directory"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// asciidoctor = mockAsciidoctor -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), _) -// !outDir.listFiles({ !it.directory && !(it.name =~ DOCINFO_FILE_PATTERN) } as FileFilter) -// } -// -// @SuppressWarnings('MethodName') -// def "Project coordinates are set automatically as attributes"() { -// given: -// project.version = '1.0.0-SNAPSHOT' -// project.group = 'com.acme' -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { -// it.attributes.'project-name' == 'test' && -// it.attributes.'project-group' == 'com.acme' && -// it.attributes.'project-version' == '1.0.0-SNAPSHOT' -// }) -// } -// -// @SuppressWarnings('MethodName') -// def "Override project coordinates with explicit attributes"() { -// given: -// project.version = '1.0.0-SNAPSHOT' -// project.group = 'com.acme' -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// options = [ -// attributes: [ -// 'project-name' : 'awesome', -// 'project-group' : 'unicorns', -// 'project-version': '1.0.0.Final' -// ] -// ] -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { -// it.attributes.'project-name' == 'awesome' && -// it.attributes.'project-group' == 'unicorns' && -// it.attributes.'project-version' == '1.0.0.Final' -// }) -// } -// -// @SuppressWarnings('MethodName') -// def "Should support multiple source documents if names are given"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// sources { -// include ASCIIDOC_SAMPLE_FILE, ASCIIDOC_SAMPLE2_FILE -// } -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), _) -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE2_FILE), _) -// } -// -// @SuppressWarnings('MethodName') -// def "Should throw exception if the file sourceDocumentName starts with underscore"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// sources { -// include ASCIIDOC_INVALID_FILE -// } -// } -// when: -// task.processAsciidocSources() -// then: -// 0 * mockAsciidoctor.renderFile(_, _) -// thrown(GradleException) -// } -// -// def "When 'resources' not specified, then copy all images to backend"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// -// sourceDir srcDir -// outputDir outDir -// backends AsciidoctorBackend.HTML5.id -// -// sources { -// include ASCIIDOC_SAMPLE_FILE -// } -// -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockCopyProxy.copy(_, _) -// } -// -// def "When 'resources' not specified and more than one backend, then copy all images to every backend"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// -// sourceDir srcDir -// outputDir outDir -// backends AsciidoctorBackend.HTML5.id, AsciidoctorBackend.DOCBOOK.id -// -// sources { -// include ASCIIDOC_SAMPLE_FILE -// } -// -// } -// when: -// task.processAsciidocSources() -// then: -// 1 * mockCopyProxy.copy(new File(outDir, AsciidoctorBackend.HTML5.id), _) -// 1 * mockCopyProxy.copy(new File(outDir, AsciidoctorBackend.DOCBOOK.id), _) -// } -// -// def "When 'resources' are specified, then copy according to all patterns"() { -// given: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// -// sourceDir srcDir -// outputDir outDir -// backends AsciidoctorBackend.HTML5.id, AsciidoctorBackend.DOCBOOK.id -// -// sources { -// include ASCIIDOC_SAMPLE_FILE -// } -// -// resources { -// from(sourceDir) { -// include 'images/**' -// } -// } -// } -// -// when: -// task.processAsciidocSources() -// then: -// 1 * mockCopyProxy.copy(new File(outDir, AsciidoctorBackend.HTML5.id), _) -// 1 * mockCopyProxy.copy(new File(outDir, AsciidoctorBackend.DOCBOOK.id), _) -// } -// -// def "set output dir to something else than the default"() { -// given: -// project.version = '1.0.0-SNAPSHOT' -// project.group = 'com.acme' -// -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// asciidoctor = mockAsciidoctor -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// } -// project.buildDir = '/tmp/testbuild/asciidoctor' -// -// when: -// task.processAsciidocSources() -// -// then: 'the html files must be in testbuild/asciidoctor ' -// task.outputDir.absolutePath.replace('\\', '/').contains('testbuild/asciidoctor') -// 2 * mockAsciidoctor.renderFile(_, { it.to_dir.startsWith(project.buildDir.absolutePath) }) -// } -// -// -// def "GroovyStrings in options and attributes are converted into Strings"() { -// given: -// String variable = 'bar' -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// options = [ -// template_dirs: ["${project.projectDir}/templates/haml"] -// ] -// attributes = [ -// foo: "${variable}" -// ] -// resourceCopyProxy = mockCopyProxy -// sourceDir srcDir -// outputDir = outDir -// } -// -// when: -// task.processAsciidocSources() -// -// then: -// 1 * mockAsciidoctor.renderFile(new File(task.sourceDir, ASCIIDOC_SAMPLE_FILE), { Map props -> -// props.template_dirs*.class == [String] && -// props.attributes.foo.class == String -// }) -// } -// -// void 'Should require libraries'() { -// -// when: -// Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { -// resourceCopyProxy = mockCopyProxy -// sourceDir = srcDir -// outputDir = outDir -// sources { -// include ASCIIDOC_SAMPLE_FILE -// } -// requires 'asciidoctor-pdf' -// } -// -// task.processAsciidocSources() -// then: -// 1 * mockAsciidoctor.requireLibrary('asciidoctor-pdf') -// } + static final String ATTRS_AS_STRING = 'toc=right source-highlighter=coderay' + static final String HIGHLIGTHER = 'coderay' + + @Unroll + void 'Should support #type value for attributes embedded in options'() { + given: + AsciidoctorTask task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { + options = [ + attributes: data + ] + } + + Map options = task.getOptions() + Map attrs = task.getAttributes() + + expect: + verifyAll { + options.isEmpty() + attrs.containsKey('toc') + attrs.containsKey('source-highlighter') + } + verifyAll { + attrs.toc == 'right' + attrs.'source-highlighter' == HIGHLIGTHER + } + + where: + type | data + 'String' | 'toc=right source-highlighter=coderay' + 'GString' | "${ATTRS_AS_STRING}" + 'List' | ['toc=right', "source-highlighter=${HIGHLIGTHER}"] + } + + void "Throws exception when attributes embedded in options is an unsupported type"() { + when: + AsciidoctorTask task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { + options = [ + attributes: 23 + ] + } + + then: + thrown(GradleException) + } + + void 'GStrings in options and attributes are converted into Strings'() { + given: + String variable = 'bar' + Task task = project.tasks.create(name: ASCIIDOCTOR, type: AsciidoctorTask) { + options = [ + template_dirs: ["${project.projectDir}/templates/haml"] + ] + attributes = [ + foo: "${variable}" + ] + } + Map options = task.getOptions() + Map attrs = task.getAttributes() + + expect: + verifyAll { + options.containsKey('template_dirs') + attrs.containsKey('foo') + } + verifyAll { + options.template_dirs[0].endsWith('haml') + attrs.'foo' == variable + } + + } }