added working test casres for groovy style markup builders
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package std.util
|
||||
|
||||
import java.util.Map as JMap
|
||||
import java.util.Map.Entry as JEntry
|
||||
|
||||
// Map APIs
|
||||
|
||||
@@ -12,6 +13,14 @@ val JMap<*,*>.size : Int
|
||||
val JMap<*,*>.empty : Boolean
|
||||
get() = isEmpty()
|
||||
|
||||
/** Returns the key of the entry */
|
||||
val <K,V> JEntry<K,V>.key : K
|
||||
get() = getKey()
|
||||
|
||||
/** Returns the value of the entry */
|
||||
val <K,V> JEntry<K,V>.value : V
|
||||
get() = getValue()
|
||||
|
||||
/** Returns the value for the given key or returns the result of the defaultValue function if there was no entry for the given key */
|
||||
inline fun <K,V> java.util.Map<K,V>.getOrElse(key: K, defaultValue: ()-> V) : V {
|
||||
val current = this.get(key)
|
||||
|
||||
@@ -12,9 +12,16 @@ trait Factory<T> {
|
||||
fun create() : T
|
||||
}
|
||||
|
||||
abstract class Element
|
||||
abstract class Element {
|
||||
abstract fun appendTo(builder: StringBuilder): Unit
|
||||
|
||||
class TextElement(val text : String) : Element
|
||||
}
|
||||
|
||||
class TextElement(val text : String) : Element {
|
||||
override fun appendTo(builder: StringBuilder) {
|
||||
builder.append(text)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Tag(val name : String) : Element {
|
||||
val children = ArrayList<Element>()
|
||||
@@ -22,11 +29,46 @@ abstract class Tag(val name : String) : Element {
|
||||
|
||||
protected fun initTag<T : Element>(init : T.()-> Unit) : T
|
||||
where class object T : Factory<T> {
|
||||
val tag = T.create()
|
||||
val tag = try {
|
||||
T.create()
|
||||
} catch (e: NullPointerException) {
|
||||
val typeName = javaClass.getName()
|
||||
throw UnsupportedOperationException("No class object create() method for $typeName")
|
||||
}
|
||||
tag.init()
|
||||
children.add(tag)
|
||||
return tag
|
||||
}
|
||||
|
||||
override fun appendTo(builder: StringBuilder): Unit {
|
||||
builder.append("<")
|
||||
builder.append(name)
|
||||
if (!attributes.isEmpty()) {
|
||||
for (e in attributes.entrySet()) {
|
||||
if (e != null) {
|
||||
builder.append(" ${e.key}=\"${e.value}\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
if (children.isEmpty()) {
|
||||
builder.append("/>")
|
||||
} else {
|
||||
builder.append(">")
|
||||
for (c in children) {
|
||||
c.appendTo(builder)
|
||||
}
|
||||
builder.append("<")
|
||||
builder.append(name)
|
||||
builder.append(">")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun toString(): String {
|
||||
val builder = StringBuilder()
|
||||
appendTo(builder)
|
||||
return builder.toString().sure()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TagWithText(name : String) : Tag(name) {
|
||||
@@ -53,7 +95,11 @@ class Head() : TagWithText("head") {
|
||||
fun title(init : Title.()-> Unit) = initTag(init)
|
||||
}
|
||||
|
||||
class Title() : TagWithText("title")
|
||||
class Title() : TagWithText("title") {
|
||||
class object : Factory<Title> {
|
||||
override fun create() = Title()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class BodyTag(name : String) : TagWithText(name) {
|
||||
}
|
||||
@@ -68,20 +114,38 @@ class Body() : BodyTag("body") {
|
||||
fun h1(init : H1.()-> Unit) = initTag(init)
|
||||
|
||||
fun a(href : String) {
|
||||
a(href) {}
|
||||
a(href, {})
|
||||
}
|
||||
|
||||
fun a(href : String, init : A.()-> Unit) {
|
||||
val a = initTag(init)
|
||||
a.href = href
|
||||
a.attributes.put("href", href)
|
||||
}
|
||||
}
|
||||
|
||||
class B() : BodyTag("b")
|
||||
class P() : BodyTag("p")
|
||||
class H1() : BodyTag("h1")
|
||||
class B() : BodyTag("b") {
|
||||
class object : Factory<B> {
|
||||
override fun create() = B()
|
||||
}
|
||||
}
|
||||
|
||||
class P() : BodyTag("p") {
|
||||
class object : Factory<P> {
|
||||
override fun create() = P()
|
||||
}
|
||||
}
|
||||
class H1() : BodyTag("h1") {
|
||||
class object : Factory<H1> {
|
||||
override fun create() = H1()
|
||||
}
|
||||
}
|
||||
|
||||
class A() : BodyTag("a") {
|
||||
class object : Factory<A> {
|
||||
override fun create() = A()
|
||||
}
|
||||
|
||||
var href: String? = null
|
||||
/*
|
||||
TODO this doesn't compile
|
||||
|
||||
@@ -8,60 +8,89 @@ import std.util.*
|
||||
import std.test.*
|
||||
import java.util.*
|
||||
|
||||
/*
|
||||
TODO generates compiler error
|
||||
see: http://youtrack.jetbrains.net/issue/KT-866
|
||||
|
||||
val justBody = body {
|
||||
+"Hello world"
|
||||
}
|
||||
+"Hello world"
|
||||
}
|
||||
|
||||
fun result(args : List<String>) =
|
||||
html {
|
||||
head {
|
||||
title {+"XML encoding with Kotlin"}
|
||||
}
|
||||
body {
|
||||
h1 {+"XML encoding with Kotlin"}
|
||||
p {+"this format can be used as an alternative markup to XML"}
|
||||
html {
|
||||
head {
|
||||
title {+"XML encoding with Kotlin"}
|
||||
}
|
||||
body {
|
||||
h1 {+"XML encoding with Kotlin"}
|
||||
p {+"this format can be used as an alternative markup to XML"}
|
||||
|
||||
// an element with attributes and text content
|
||||
// an element with attributes and text content
|
||||
a(href = "http://jetbrains.com/kotlin") {+"Kotlin"}
|
||||
|
||||
// mixed content
|
||||
p {
|
||||
+"This is some"
|
||||
b {+"mixed"}
|
||||
+"text. For more see the"
|
||||
a(href = "http://jetbrains.com/kotlin") {+"Kotlin"}
|
||||
+"project"
|
||||
}
|
||||
p {+"some text"}
|
||||
|
||||
// mixed content
|
||||
p {
|
||||
+"This is some"
|
||||
b {+"mixed"}
|
||||
+"text. For more see the"
|
||||
a(href = "http://jetbrains.com/kotlin") {+"Kotlin"}
|
||||
+"project"
|
||||
}
|
||||
p {+"some text"}
|
||||
|
||||
// content generated by
|
||||
p {
|
||||
for (arg in args)
|
||||
+arg
|
||||
}
|
||||
// content generated by
|
||||
p {
|
||||
for (arg in args)
|
||||
+arg
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/** Create a bad element which doesn't have a class object create() method */
|
||||
class BadElem() : BodyTag("bad") {
|
||||
}
|
||||
|
||||
/** Creates a bad body to test out badly defined elements */
|
||||
class BadBody() : BodyTag("badBody") {
|
||||
fun bad(init : BadElem.()-> Unit) = initTag(init)
|
||||
}
|
||||
|
||||
fun badBody(init: BadBody.()-> Unit): BadBody {
|
||||
val elem = BadBody()
|
||||
elem.init()
|
||||
return elem
|
||||
}
|
||||
|
||||
class TemplateHtmlTest() : TestSupport() {
|
||||
fun testNoneCompileYet() {
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: compiler bug
|
||||
see: http://youtrack.jetbrains.net/issue/KT-866
|
||||
|
||||
fun testJustBody() {
|
||||
println(justBody)
|
||||
assertEquals("<body>Hello world<body>", justBody.toString())
|
||||
}
|
||||
|
||||
fun testEmbeddedSimpleBody() {
|
||||
val e = body {
|
||||
+"body with text"
|
||||
}
|
||||
assertEquals("<body>body with text<body>", e.toString())
|
||||
}
|
||||
|
||||
fun testEmbeddedBodyWithNestedBold() {
|
||||
val e = body {
|
||||
b{
|
||||
+"this is bold"
|
||||
}
|
||||
}
|
||||
assertEquals("<body><b>this is bold<b><body>", e.toString())
|
||||
}
|
||||
|
||||
fun testEmbeddedBodyWithNestedLinks() {
|
||||
val e = body {
|
||||
a("http://jetbrains.com/kotlin") {
|
||||
+"link text"
|
||||
}
|
||||
}
|
||||
assertEquals("<body><a href=\"http://jetbrains.com/kotlin\">link text<a><body>", e.toString())
|
||||
}
|
||||
|
||||
fun testHtmlFunction() {
|
||||
val text = result(arrayList("a", "b", "c"))
|
||||
println(text)
|
||||
val e = result(arrayList("a", "b", "c"))
|
||||
assertEquals("""<html><head><title>XML encoding with Kotlin<title><head><body><h1>XML encoding with Kotlin<h1><p>this format can be used as an alternative markup to XML<p><a href="http://jetbrains.com/kotlin">Kotlin<a><b>mixed<b><a href="http://jetbrains.com/kotlin">Kotlin<a><p>This is sometext. For more see theproject<p><p>some text<p><p>abc<p><body><html>""", e.toString())
|
||||
}
|
||||
|
||||
fun testEmbeddedFunction() {
|
||||
@@ -69,11 +98,21 @@ class TemplateHtmlTest() : TestSupport() {
|
||||
head {
|
||||
title {+"XML encoding with Kotlin"}
|
||||
}
|
||||
body {
|
||||
a("http://jetbrains.com/kotlin")
|
||||
}
|
||||
body {
|
||||
a("http://jetbrains.com/kotlin")
|
||||
}
|
||||
}
|
||||
assertEquals("<html><head><title>XML encoding with Kotlin<title><head><body><a href=\"http://jetbrains.com/kotlin\"/><body><html>", e.toString())
|
||||
}
|
||||
|
||||
fun testBadlyDefinedElement() {
|
||||
failsWith<UnsupportedOperationException>{
|
||||
val e = badBody {
|
||||
bad{
|
||||
+"Bad Element Text"
|
||||
}
|
||||
}
|
||||
println("bad body: $e")
|
||||
}
|
||||
println(e)
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -102,6 +102,17 @@ fun fails(block: ()-> Any) {
|
||||
block()
|
||||
Assert.fail("Expected an exception to be thrown")
|
||||
} catch (e: Exception) {
|
||||
println("Caught excepted exception: $e")
|
||||
// OK
|
||||
}
|
||||
}
|
||||
|
||||
fun <T: Exception> failsWith(block: ()-> Any) {
|
||||
try {
|
||||
block()
|
||||
Assert.fail("Expected an exception to be thrown")
|
||||
} catch (e: T) {
|
||||
println("Caught excepted exception: $e")
|
||||
// OK
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user