aboutsummaryrefslogtreecommitdiff
path: root/test-tools/src/main/kotlin/matchers/content/ContentMatchersDsl.kt
diff options
context:
space:
mode:
Diffstat (limited to 'test-tools/src/main/kotlin/matchers/content/ContentMatchersDsl.kt')
-rw-r--r--test-tools/src/main/kotlin/matchers/content/ContentMatchersDsl.kt101
1 files changed, 101 insertions, 0 deletions
diff --git a/test-tools/src/main/kotlin/matchers/content/ContentMatchersDsl.kt b/test-tools/src/main/kotlin/matchers/content/ContentMatchersDsl.kt
new file mode 100644
index 00000000..01abab28
--- /dev/null
+++ b/test-tools/src/main/kotlin/matchers/content/ContentMatchersDsl.kt
@@ -0,0 +1,101 @@
+package matchers.content
+
+import assertk.assertThat
+import assertk.assertions.contains
+import assertk.assertions.isEqualTo
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.test.tools.matchers.content.*
+import kotlin.reflect.KClass
+
+// entry point:
+fun ContentNode.assertNode(block: ContentMatcherBuilder<ContentComposite>.() -> Unit) {
+ val matcher = ContentMatcherBuilder(ContentComposite::class).apply(block).build()
+ try {
+ matcher.tryMatch(this)
+ } catch (e: MatcherError) {
+ throw AssertionError(e.message + "\n" + matcher.toDebugString(e.anchor, e.anchorAfter))
+ }
+}
+
+
+// DSL:
+@DslMarker
+annotation class ContentMatchersDsl
+
+@ContentMatchersDsl
+class ContentMatcherBuilder<T : ContentComposite> @PublishedApi internal constructor(private val kclass: KClass<T>) {
+ @PublishedApi
+ internal val children = mutableListOf<MatcherElement>()
+ internal val assertions = mutableListOf<T.() -> Unit>()
+
+ fun build() = CompositeMatcher(kclass, children) { assertions.forEach { it() } }
+
+ // part of DSL that cannot be defined as an extension
+ operator fun String.unaryPlus() {
+ children += TextMatcher(this)
+ }
+}
+
+fun <T : ContentComposite> ContentMatcherBuilder<T>.check(assertion: T.() -> Unit) {
+ assertions += assertion
+}
+
+inline fun <reified S : ContentComposite> ContentMatcherBuilder<*>.composite(
+ block: ContentMatcherBuilder<S>.() -> Unit
+) {
+ children += ContentMatcherBuilder(S::class).apply(block).build()
+}
+
+inline fun <reified S : ContentNode> ContentMatcherBuilder<*>.node(noinline assertions: S.() -> Unit = {}) {
+ children += NodeMatcher(S::class, assertions)
+}
+
+fun ContentMatcherBuilder<*>.skipAllNotMatching() {
+ children += Anything
+}
+
+
+// Convenience functions:
+fun ContentMatcherBuilder<*>.group(block: ContentMatcherBuilder<ContentGroup>.() -> Unit) = composite(block)
+
+fun ContentMatcherBuilder<*>.header(expectedLevel: Int? = null, block: ContentMatcherBuilder<ContentHeader>.() -> Unit) =
+ composite<ContentHeader> {
+ block()
+ check { if (expectedLevel != null) assertThat(this::level).isEqualTo(expectedLevel) }
+ }
+
+fun ContentMatcherBuilder<*>.p(block: ContentMatcherBuilder<ContentGroup>.() -> Unit) =
+ composite<ContentGroup> {
+ block()
+ check { assertThat(this::style).contains(TextStyle.Paragraph) }
+ }
+
+fun ContentMatcherBuilder<*>.link(block: ContentMatcherBuilder<ContentLink>.() -> Unit) = composite(block)
+
+fun ContentMatcherBuilder<*>.table(block: ContentMatcherBuilder<ContentTable>.() -> Unit) = composite(block)
+
+fun ContentMatcherBuilder<*>.platformHinted(block: ContentMatcherBuilder<ContentGroup>.() -> Unit) =
+ composite<PlatformHintedContent> { group(block) }
+
+fun ContentMatcherBuilder<*>.br() = node<ContentBreakLine>()
+
+fun ContentMatcherBuilder<*>.somewhere(block: ContentMatcherBuilder<*>.() -> Unit) {
+ skipAllNotMatching()
+ block()
+ skipAllNotMatching()
+}
+
+fun ContentMatcherBuilder<*>.divergentGroup(block: ContentMatcherBuilder<ContentDivergentGroup>.() -> Unit) =
+ composite(block)
+
+fun ContentMatcherBuilder<ContentDivergentGroup>.divergentInstance(block: ContentMatcherBuilder<ContentDivergentInstance>.() -> Unit) =
+ composite(block)
+
+fun ContentMatcherBuilder<ContentDivergentInstance>.before(block: ContentMatcherBuilder<ContentComposite>.() -> Unit) =
+ composite(block)
+
+fun ContentMatcherBuilder<ContentDivergentInstance>.divergent(block: ContentMatcherBuilder<ContentComposite>.() -> Unit) =
+ composite(block)
+
+fun ContentMatcherBuilder<ContentDivergentInstance>.after(block: ContentMatcherBuilder<ContentComposite>.() -> Unit) =
+ composite(block) \ No newline at end of file