added working test casres for groovy style markup builders

This commit is contained in:
James Strachan
2012-01-04 12:59:37 +00:00
parent 8cfc979c10
commit 8c40aa58af
4 changed files with 175 additions and 52 deletions
+9
View File
@@ -1,6 +1,7 @@
package std.util package std.util
import java.util.Map as JMap import java.util.Map as JMap
import java.util.Map.Entry as JEntry
// Map APIs // Map APIs
@@ -12,6 +13,14 @@ val JMap<*,*>.size : Int
val JMap<*,*>.empty : Boolean val JMap<*,*>.empty : Boolean
get() = isEmpty() 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 */ /** 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 { inline fun <K,V> java.util.Map<K,V>.getOrElse(key: K, defaultValue: ()-> V) : V {
val current = this.get(key) val current = this.get(key)
+72 -8
View File
@@ -12,9 +12,16 @@ trait Factory<T> {
fun create() : 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 { abstract class Tag(val name : String) : Element {
val children = ArrayList<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 protected fun initTag<T : Element>(init : T.()-> Unit) : T
where class object T : Factory<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() tag.init()
children.add(tag) children.add(tag)
return 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) { abstract class TagWithText(name : String) : Tag(name) {
@@ -53,7 +95,11 @@ class Head() : TagWithText("head") {
fun title(init : Title.()-> Unit) = initTag(init) 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) { abstract class BodyTag(name : String) : TagWithText(name) {
} }
@@ -68,20 +114,38 @@ class Body() : BodyTag("body") {
fun h1(init : H1.()-> Unit) = initTag(init) fun h1(init : H1.()-> Unit) = initTag(init)
fun a(href : String) { fun a(href : String) {
a(href) {} a(href, {})
} }
fun a(href : String, init : A.()-> Unit) { fun a(href : String, init : A.()-> Unit) {
val a = initTag(init) val a = initTag(init)
a.href = href a.href = href
a.attributes.put("href", href)
} }
} }
class B() : BodyTag("b") class B() : BodyTag("b") {
class P() : BodyTag("p") class object : Factory<B> {
class H1() : BodyTag("h1") 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 A() : BodyTag("a") {
class object : Factory<A> {
override fun create() = A()
}
var href: String? = null var href: String? = null
/* /*
TODO this doesn't compile TODO this doesn't compile
+83 -44
View File
@@ -8,60 +8,89 @@ import std.util.*
import std.test.* import std.test.*
import java.util.* import java.util.*
/*
TODO generates compiler error
see: http://youtrack.jetbrains.net/issue/KT-866
val justBody = body { val justBody = body {
+"Hello world" +"Hello world"
} }
fun result(args : List<String>) = fun result(args : List<String>) =
html { html {
head { head {
title {+"XML encoding with Kotlin"} title {+"XML encoding with Kotlin"}
} }
body { body {
h1 {+"XML encoding with Kotlin"} h1 {+"XML encoding with Kotlin"}
p {+"this format can be used as an alternative markup to XML"} 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"} a(href = "http://jetbrains.com/kotlin") {+"Kotlin"}
+"project"
}
p {+"some text"}
// mixed content // content generated by
p { p {
+"This is some" for (arg in args)
b {+"mixed"} +arg
+"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
}
} }
} }
*/ }
/** 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() { class TemplateHtmlTest() : TestSupport() {
fun testNoneCompileYet() {
}
/*
TODO: compiler bug
see: http://youtrack.jetbrains.net/issue/KT-866
fun testJustBody() { 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() { fun testHtmlFunction() {
val text = result(arrayList("a", "b", "c")) val e = result(arrayList("a", "b", "c"))
println(text) 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() { fun testEmbeddedFunction() {
@@ -69,11 +98,21 @@ class TemplateHtmlTest() : TestSupport() {
head { head {
title {+"XML encoding with Kotlin"} title {+"XML encoding with Kotlin"}
} }
body { body {
a("http://jetbrains.com/kotlin") 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)
} }
*/
} }
+11
View File
@@ -102,6 +102,17 @@ fun fails(block: ()-> Any) {
block() block()
Assert.fail("Expected an exception to be thrown") Assert.fail("Expected an exception to be thrown")
} catch (e: Exception) { } 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 // OK
} }
} }