Skip to content

Commit

Permalink
Got the controller tests working again and implemented the # route tag
Browse files Browse the repository at this point in the history
  • Loading branch information
ajselvig committed Dec 29, 2012
1 parent 0e7fe3a commit c61345f
Show file tree
Hide file tree
Showing 19 changed files with 414 additions and 115 deletions.
9 changes: 9 additions & 0 deletions .idea/libraries/javassist_3_12_1_GA.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

252 changes: 172 additions & 80 deletions .idea/workspace.xml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions KaraDemo/src/karademo/controllers/HomeController.kt
Expand Up @@ -15,6 +15,8 @@ class HomeController() : BaseController(DefaultLayout()) {
}

Post("/updatebook") fun update() : ActionResult {
println("parameters:")
println(params.getHash("book").toString())
return RedirectResult("/forms")
}

Expand All @@ -24,8 +26,6 @@ class HomeController() : BaseController(DefaultLayout()) {
isPublished = true
}
//(this.session).setAttribute("hello", "world")
if (book.isPublished)
throw RuntimeException("This is an exception!")
return Forms(book)
}

Expand Down
2 changes: 1 addition & 1 deletion KaraExec/src/Main.kt
Expand Up @@ -35,7 +35,6 @@ Commands:
c, config Show the application's configuration for the current environment
g, generate Generates a new project or file (see below)
h, help Show this help message
u, update Updates the application's Kara dependency to the latest version
s, server Run the Kara server on the current directory
Options:
Expand All @@ -48,6 +47,7 @@ Generators:
project <name> Generates a new Kara project with the given name.
Use the --package=<package> option to specify a package
that's different than the project name.
update Updates the application's Kara dependency to the latest version
controller <name> Generates a new controller with the given name.
"Controller" will be automatically appended to the name)
view <controller> <view> Generate a new view for the given controller.
Expand Down
15 changes: 12 additions & 3 deletions KaraLib/src/kara/controllers/ActionInfo.kt
Expand Up @@ -33,8 +33,9 @@ class ActionInfo(val route : String, val controller : BaseController, val method
return true
}

public fun getParams(url : String, query : String?) : RouteParams {

public fun getParams(request : HttpServletRequest) : RouteParams {
val url = request.getRequestURI()!!
val query = request.getQueryString()
val params = RouteParams()

// parse the query string
Expand All @@ -58,11 +59,19 @@ class ActionInfo(val route : String, val controller : BaseController, val method
val routeComp = routeComps[i]
routeComp.getParam(params, comp)
}

// parse the form parameters
for (name in request.getParameterNames()) {
val value = request.getParameter(name)!!
params[name] = value
}

return params
}

/** Execute the action based on the given request and populate the response. */
public fun exec(val appConfig: AppConfig, request: HttpServletRequest, response : HttpServletResponse) {
val params = getParams(request.getRequestURI()!!, request.getQueryString())
val params = getParams(request)
controller.beforeRequest(request, response, params)
val context = ActionContext(appConfig, request, response, params)

Expand Down
8 changes: 4 additions & 4 deletions KaraLib/src/kara/controllers/Annotations.kt
Expand Up @@ -4,16 +4,16 @@ import java.lang.annotation.*

/** Used to annotate actions that respond to GET requests.
*/
Retention(RetentionPolicy.RUNTIME) annotation class Get(val route : String = "[default]")
Retention(RetentionPolicy.RUNTIME) annotation class Get(val route : String = "")

/** Used to annotate actions that respond to POST requests.
*/
Retention(RetentionPolicy.RUNTIME) annotation class Post(val route : String = "[default]")
Retention(RetentionPolicy.RUNTIME) annotation class Post(val route : String = "")

/** Used to annotate actions that respond to PUT requests.
*/
Retention(RetentionPolicy.RUNTIME) annotation class Put(val route : String = "[default]")
Retention(RetentionPolicy.RUNTIME) annotation class Put(val route : String = "")

/** Used to annotate actions that respond to DELETE requests.
*/
Retention(RetentionPolicy.RUNTIME) annotation class Delete(val route : String = "[default]")
Retention(RetentionPolicy.RUNTIME) annotation class Delete(val route : String = "")
9 changes: 6 additions & 3 deletions KaraLib/src/kara/controllers/Dispatcher.kt
Expand Up @@ -82,13 +82,16 @@ class Dispatcher() {
fun parseAction(annString : String, controller : BaseController, method : Method) {
// get the route based on the annotation and the controller
var route = annString.substring(annString.indexOf('=')+1, annString.indexOf(')'))
if (!annString.contains("=") || route == "[default]") {
route = method.getName()?.toLowerCase() as String
}
// if (!annString.contains("=") || route.length() == 0) {
// route = method.getName()?.toLowerCase() as String
// }
route = route.replace("#", method.getName()?.toLowerCase()!!)
val root = controller.root
if (!route.startsWith("/")) {
route = root + route
}
if (route.length() > 1 && route.endsWith("/"))
route = route.substring(0, route.length()-1)

val actionInfo = ActionInfo(route, controller, method)
logger.debug("adding action: " + actionInfo.toString());
Expand Down
15 changes: 15 additions & 0 deletions KaraLib/src/kara/controllers/RouteParams.kt
Expand Up @@ -40,6 +40,21 @@ class RouteParams() {
return _list.size()
}

/** Gets a hash with the nested values of the given name. */
fun getHash(name : String) : HashMap<String,String> {
val map = HashMap<String,String>()
val prefix = name + "["
for (key in _map.keySet()) {
if (key.startsWith(prefix)) {
var subkey = key.replace(prefix, "")
subkey = subkey.substring(0, subkey.length()-1)
val value = _map[key]!!
map[subkey] = value
}
}
return map
}

public fun toString() : String {
val pairs = _map.iterator().map { it ->
"${it.getKey()}: ${it.getValue()}"
Expand Down
6 changes: 6 additions & 0 deletions KaraTests/KaraTests.iml
Expand Up @@ -10,6 +10,12 @@
<orderEntry type="module" module-name="KaraLib" />
<orderEntry type="library" name="KotlinRuntime" level="project" />
<orderEntry type="library" name="javax.servlet-3.0.0.v201112011016" level="project" />
<orderEntry type="library" name="slf4j-log4j12-1.6.6" level="project" />
<orderEntry type="library" name="log4j-1.2.17" level="project" />
<orderEntry type="library" name="guava-11.0.2" level="project" />
<orderEntry type="library" name="slf4j-api-1.6.6" level="project" />
<orderEntry type="library" name="reflections-0.9.8" level="project" />
<orderEntry type="library" name="javassist-3.12.1.GA" level="project" />
</component>
</module>

5 changes: 4 additions & 1 deletion KaraTests/src/karatests/controllers/ActionTests.kt
Expand Up @@ -9,7 +9,7 @@ import kara.config.AppConfig


/** Tests for executing actions */
fun runActionTests(args : Array<String>) {
fun runActionTests() {

initMockDispatchWithReflection()

Expand All @@ -18,6 +18,9 @@ fun runActionTests(args : Array<String>) {
assertTrue(output?.contains("Default Layout") as Boolean, "Home view contains layout")
assertTrue(output?.contains("Welcome Home") as Boolean, "Home view contains view")

response = mockDispatch("GET", "/foo/blank")
assertEquals("blank", response.stringOutput())

response = mockDispatch("GET", "/foo/bar")
assertEquals("bar", response.stringOutput())

Expand Down
33 changes: 20 additions & 13 deletions KaraTests/src/karatests/controllers/DispatchTests.kt
Expand Up @@ -3,9 +3,10 @@ package karatests.controllers
import kara.controllers.Dispatcher
import kotlin.test.*
import kara.config.AppConfig
import karatests.mock.mockRequest

/** Tests for dispatching routes to get action info. */
fun runDispatchTests(args : Array<String>) {
fun runDispatchTests() {

val appConfig = AppConfig("", "development")
appConfig["kara.appPackage"] = "karatests.controllers"
Expand All @@ -27,33 +28,39 @@ fun runDispatchTests(args : Array<String>) {

dispatcher.match("GET", "/foo/foobar") // default action name

actionInfo = dispatcher.match("GET", "/foo/bar/list")!! // unnamed param
var params = actionInfo.getParams("/foo/bar/list", "")
var request = mockRequest("GET", "/foo/bar/list")
actionInfo = dispatcher.match("GET", request.getRequestURI()!!)!! // unnamed param
var params = actionInfo.getParams(request)
assertEquals("bar", params[0])

actionInfo = dispatcher.match("GET", "/foo/complex/bar/list/42")!! // named and unnamed params
params = actionInfo.getParams("/foo/complex/bar/list/42", "")
request = mockRequest("GET", "/foo/complex/bar/list/42")
actionInfo = dispatcher.match("GET", request.getRequestURI()!!)!! // named and unnamed params
params = actionInfo.getParams(request)
assertEquals("bar", params[0])
assertEquals("42", params["id"])
assertEquals(2, params.size())

// crud controller
actionInfo = dispatcher.match("GET", "/crud?name=value")!! // empty route with parameters
request = mockRequest("GET", "/crud?name=value")
actionInfo = dispatcher.match("GET", request.getRequestURI()!!)!! // empty route with parameters
assertEquals(CrudController().javaClass, actionInfo.controller.javaClass)
params = actionInfo.getParams("/crud?name=value", "")
params = actionInfo.getParams(request)
assertEquals("value", params["name"])

actionInfo = dispatcher.match("GET", "/crud/42")!! // named parameter
params = actionInfo.getParams("/crud/42", "")
request = mockRequest("GET", "/crud/42")
actionInfo = dispatcher.match("GET", request.getRequestURI()!!)!! // named parameter
params = actionInfo.getParams(request)
assertEquals("42", params["id"])

dispatcher.match("POST", "/crud") // models

actionInfo = dispatcher.match("PUT", "/crud/42")!! // put
params = actionInfo.getParams("/crud/42", "")
request = mockRequest("PUT", "/crud/42")
actionInfo = dispatcher.match("PUT", request.getRequestURI()!!)!! // put
params = actionInfo.getParams(request)
assertEquals("42", params["id"])

actionInfo = dispatcher.match("DELETE", "/crud/42")!! // delete
params = actionInfo.getParams("/crud/42", "")
request = mockRequest("DELETE", "/crud/42")
actionInfo = dispatcher.match("DELETE", request.getRequestURI()!!)!! // delete
params = actionInfo.getParams(request)
assertEquals("42", params["id"])
}
6 changes: 5 additions & 1 deletion KaraTests/src/karatests/controllers/FooController.kt
Expand Up @@ -5,6 +5,10 @@ import kara.controllers.*

class FooController() : BaseController() {

Get("#") fun blank() : ActionResult {
return TextResult("blank")
}

Get("bar") fun bar() : ActionResult {
return TextResult("bar")
}
Expand All @@ -13,7 +17,7 @@ class FooController() : BaseController() {
return TextResult("bar/baz")
}

Get("[default]") fun foobar() : ActionResult {
Get("#") fun foobar() : ActionResult {
return TextResult("foobar")
}

Expand Down
7 changes: 5 additions & 2 deletions KaraTests/src/karatests/controllers/Main.kt
@@ -1,9 +1,12 @@
package karatests.controllers

import org.apache.log4j.BasicConfigurator


/** Tests for dispatching routes to get action info. */
fun main(args : Array<String>) {
BasicConfigurator.configure()

runDispatchTests(args)
runActionTests(args)
runDispatchTests()
runActionTests()
}
8 changes: 8 additions & 0 deletions KaraTests/src/karatests/mock/MockDispatch.kt
Expand Up @@ -9,6 +9,7 @@ val _dispatcher = Dispatcher()
val _mockAppConfig = AppConfig("", "test")

public fun initMockDispatchWithReflection() {
_mockAppConfig["kara.appPackage"] = "karatests.controllers"
_dispatcher.initWithReflection(_mockAppConfig)
}

Expand All @@ -19,4 +20,11 @@ public fun mockDispatch(httpMethod : String, url : String) : MockHttpServletResp
val response = MockHttpServletResponse()
_dispatcher.dispatch(_mockAppConfig, request, response)
return response
}


/** Creates a HttpServletRequest with the given method and url*/
public fun mockRequest(httpMethod : String, url : String) : MockHttpServletRequest {
val request = MockHttpServletRequest(httpMethod, url)
return request
}
15 changes: 12 additions & 3 deletions KaraTests/src/karatests/mock/MockHttpServletRequest.kt
Expand Up @@ -9,6 +9,9 @@ import javax.servlet.ServletInputStream
import java.util.Locale
import java.io.BufferedReader
import javax.servlet.http.Cookie
import java.util.ArrayList
import java.util.HashMap
import java.util.Hashtable


class MockHttpServletRequest(method : String, url : String) : HttpServletRequest {
Expand Down Expand Up @@ -60,8 +63,11 @@ class MockHttpServletRequest(method : String, url : String) : HttpServletRequest
public override fun getSession() : HttpSession? {
throw UnsupportedOperationException()
}

val session = MockHttpSession()

public override fun getSession(p0 : Boolean) : HttpSession? {
throw UnsupportedOperationException()
return session
}
public override fun getHeaders(p0 : String?) : Enumeration<String>? {
throw UnsupportedOperationException()
Expand Down Expand Up @@ -139,16 +145,19 @@ class MockHttpServletRequest(method : String, url : String) : HttpServletRequest
throw UnsupportedOperationException()
}
public override fun getParameter(p0 : String?) : String? {
throw UnsupportedOperationException()
return params[p0]
}
public override fun getRemoteHost() : String? {
throw UnsupportedOperationException()
}
public override fun getAttributeNames() : Enumeration<String>? {
throw UnsupportedOperationException()
}

val params = Hashtable<String,String>()

public override fun getParameterNames() : Enumeration<String>? {
throw UnsupportedOperationException()
return params.keys()
}
public override fun setAttribute(p0 : String?, p1 : Any?) {
throw UnsupportedOperationException()
Expand Down

0 comments on commit c61345f

Please sign in to comment.