Last active
December 21, 2015 03:48
-
-
Save tomaslin/6244676 to your computer and use it in GitHub Desktop.
Ratpack tests from ratpack/ratpack Aug 15
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/block/BlockingSpec.groovy | |
******************************************************************************** | |
class BlockingSpec extends RatpackGroovyDslSpec { | |
def "can perform blocking operations"() { | |
when: | |
def steps = [] | |
app { | |
handlers { | |
get { | |
steps << "start" | |
exec blocking, { sleep 300; steps << "operation"; 2 }, { Integer result -> | |
steps << "then" | |
response.send result.toString() | |
} | |
steps << "end" | |
} | |
} | |
} | |
then: | |
text == "2" | |
steps == ["start", "end", "operation", "then"] | |
} | |
def "by default errors during blocking operations are forwarded to server error handler"() { | |
when: | |
app { | |
modules { | |
bind ServerErrorHandler, PrintingServerErrorHandler | |
} | |
handlers { | |
get { | |
exec blocking, | |
{ sleep 300; throw new Exception("!") }, // blocking | |
{ /* never called */ } // on success | |
} | |
} | |
} | |
then: | |
text.startsWith(new Exception("!").toString()) | |
response.statusCode == 500 | |
} | |
def "can use custom error handler"() { | |
when: | |
app { | |
handlers { | |
get { | |
exec blocking, | |
{ sleep 300; throw new Exception("!") }, // blocking | |
{ response.status(210).send("error: $it.message") }, // on error | |
{ /* never called */ } // on success | |
} | |
} | |
} | |
then: | |
text == "error: !" | |
response.statusCode == 210 | |
} | |
def "errors in custom error handlers are forwarded to the server error handler"() { | |
when: | |
app { | |
modules { | |
bind ServerErrorHandler, PrintingServerErrorHandler | |
} | |
handlers { | |
get { | |
exec blocking, | |
{ throw new Exception("!") }, | |
{ throw new Exception("!!", it) }, | |
{ /* never called */ } | |
} | |
} | |
} | |
then: | |
text.startsWith(new Exception("!!", new Exception("!")).toString()) | |
response.statusCode == 500 | |
} | |
def "errors in success handlers are forwarded to the server error handler"() { | |
when: | |
app { | |
modules { | |
bind ServerErrorHandler, PrintingServerErrorHandler | |
} | |
handlers { | |
get { | |
exec blocking, | |
{ 1 }, | |
{ throw new Exception("!") }, // not expecting this to be called | |
{ throw new Exception("success") } | |
} | |
} | |
} | |
then: | |
text.startsWith(new Exception("success").toString()) | |
response.statusCode == 500 | |
} | |
def "closure arg type mismatch errors on success handler are handled well"() { | |
when: | |
app { | |
modules { | |
bind ServerErrorHandler, PrintingServerErrorHandler | |
} | |
handlers { | |
get { | |
exec blocking, | |
{ 1 }, | |
{ List<String> result -> response.send("unexpected") } | |
} | |
} | |
} | |
then: | |
text.startsWith "groovy.lang.MissingMethodException" | |
response.statusCode == 500 | |
} | |
def "closure arg type mismatch errors on error handler are handled well"() { | |
when: | |
app { | |
modules { | |
bind ServerErrorHandler, PrintingServerErrorHandler | |
} | |
handlers { | |
get { | |
exec blocking, | |
{ throw new Exception("!") }, | |
{ String string -> response.send("unexpected") }, | |
{ response.send("unexpected - value") } | |
} | |
} | |
} | |
then: | |
text.startsWith "groovy.lang.MissingMethodException" | |
response.statusCode == 500 | |
} | |
def "delegate in closure actions is no the arg"() { | |
when: | |
app { | |
handlers { | |
handler { | |
exec blocking, { | |
[foo: "bar"] | |
}, { | |
response.send it.toString() | |
} | |
} | |
} | |
} | |
then: | |
getText() == [foo: "bar"].toString() | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/file/StaticFileSpec.groovy | |
******************************************************************************** | |
class StaticFileSpec extends RatpackGroovyDslSpec { | |
def "root listing disabled"() { | |
given: | |
file("public/static.text") << "hello!" | |
file("public/foo/static.text") << "hello!" | |
when: | |
app { | |
handlers { | |
assets("public") | |
} | |
} | |
then: | |
get("").statusCode == FORBIDDEN.code() | |
get("foo").statusCode == FORBIDDEN.code() | |
get("foos").statusCode == NOT_FOUND.code() | |
} | |
def "can serve static file"() { | |
given: | |
def file = file("public/static.text") << "hello!" | |
when: | |
app { | |
handlers { | |
assets("public") | |
} | |
} | |
then: | |
getText("static.text") == "hello!" | |
getText("static.text") == "hello!" | |
with(head("static.text")) { | |
statusCode == OK.code() | |
asByteArray().length == 0 | |
getHeader("content-length") == file.length().toString() | |
} | |
} | |
def "can serve index files"() { | |
file("public/index.html") << "foo" | |
file("public/dir/index.xhtml") << "bar" | |
when: | |
app { | |
handlers { | |
assets("public", "index.html", "index.xhtml") | |
} | |
} | |
then: | |
getText() == "foo" | |
getText("dir") == "bar" | |
getText("dir/") == "bar" | |
} | |
def "can serve files with query strings"() { | |
given: | |
file("public/index.html") << "foo" | |
when: | |
app { | |
handlers { | |
assets("public", "index.html") | |
} | |
} | |
then: | |
getText("?abc") == "foo" | |
getText("index.html?abc") == "foo" | |
} | |
def "can map to multiple dirs"() { | |
given: | |
file("d1/f1.txt") << "1" | |
file("d2/f2.txt") << "2" | |
when: | |
app { | |
handlers { | |
prefix("a") { | |
assets("d1") | |
} | |
prefix("b") { | |
assets("d2") | |
} | |
} | |
} | |
then: | |
getText("a/f1.txt") == "1" | |
getText("b/f2.txt") == "2" | |
} | |
def "decodes URL paths correctly"() { | |
given: | |
file("d1/some other.txt") << "1" | |
file("d1/some+more.txt") << "2" | |
file("d1/path to/some+where/test.txt") << "3" | |
when: | |
app { | |
handlers { | |
assets("d1") | |
} | |
} | |
then: | |
getText("some%20other.txt") == "1" | |
getText("some+more.txt") == "2" | |
getText("path%20to/some+where/test.txt") == "3" | |
get("some+other.txt").statusCode == NOT_FOUND.code() | |
get("some%20more.txt").statusCode == NOT_FOUND.code() | |
} | |
def "can nest file system binding handlers"() { | |
given: | |
file("d1/d2/d3/dir/index.html") << "3" | |
when: | |
app { | |
handlers { | |
fileSystem("d1") { | |
fileSystem("d2") { | |
assets("d3", "index.html") | |
} | |
} | |
} | |
} | |
then: | |
getText("dir") == "3" | |
} | |
def "can bind to subpath"() { | |
given: | |
file("foo/file.txt") << "file" | |
when: | |
app { | |
handlers { | |
prefix("bar") { | |
assets("foo") | |
} | |
} | |
} | |
then: | |
get("foo/file.txt").statusCode == NOT_FOUND.code() | |
getText("bar/file.txt") == "file" | |
} | |
def "files report a last modified time"() { | |
given: | |
def file = file("public/file.txt") << "hello!" | |
and: | |
app { | |
handlers { | |
assets("public") | |
} | |
} | |
expect: | |
def response = get("file.txt") | |
response.statusCode == OK.code() | |
// compare the last modified dates formatted as milliseconds are stripped when added as a response header | |
formatDateHeader(parseDateHeader(response, LAST_MODIFIED)) == formatDateHeader(file.lastModified()) | |
} | |
def "404 when posting to a non existent asset"() { | |
given: | |
file("public/file.txt") << "a" | |
when: | |
app { | |
handlers { | |
assets("public") | |
} | |
} | |
then: | |
this.get("file.txt").statusCode == OK.code() | |
this.post("file.txt").statusCode == METHOD_NOT_ALLOWED.code() | |
this.get("nothing").statusCode == NOT_FOUND.code() | |
this.post("nothing").statusCode == NOT_FOUND.code() | |
} | |
@Unroll | |
def "asset handler returns a #statusCode if file is #state the request's if-modified-since header"() { | |
given: | |
def file = file("public/file.txt") << "hello!" | |
and: | |
app { | |
handlers { | |
assets("public") | |
} | |
} | |
and: | |
request.header IF_MODIFIED_SINCE, formatDateHeader(file.lastModified() + ifModifiedSince) | |
expect: | |
def response = get("file.txt") | |
response.statusCode == statusCode.code() | |
response.getHeader(CONTENT_LENGTH).toInteger() == contentLength | |
where: | |
ifModifiedSince | statusCode | contentLength | |
-1000 | OK | "hello!".length() | |
+1000 | OK | "hello!".length() | |
0 | NOT_MODIFIED | 0 | |
state = ifModifiedSince < 0 ? "newer than" : ifModifiedSince == 0 ? "the same age as" : "older than" | |
} | |
def "asset handler respect if-modified-since header when serving index files"() { | |
given: | |
def file = file("public/index.txt") << "hello!" | |
and: | |
app { | |
handlers { | |
assets("public", "index.txt") | |
} | |
} | |
and: | |
request.header IF_MODIFIED_SINCE, formatDateHeader(file.lastModified()) | |
expect: | |
def response = get("") | |
response.statusCode == NOT_MODIFIED.code() | |
response.getHeader(CONTENT_LENGTH).toInteger() == 0 | |
} | |
def "can serve large static file"() { | |
given: | |
def file = file("public/static.text") << RandomStringUtils.randomAscii(fileSize) | |
when: | |
app { | |
handlers { | |
assets("public") | |
} | |
} | |
then: | |
getText("static.text").bytes.length == file.length() | |
with(head("static.text")) { | |
statusCode == OK.code() | |
asByteArray().length == 0 | |
getHeader("content-length") == file.length().toString() | |
} | |
where: | |
fileSize = 2131795 // taken from original bug report | |
} | |
private static Date parseDateHeader(Response response, String name) { | |
HttpHeaderDateFormat.get().parse(response.getHeader(name)) | |
} | |
private static String formatDateHeader(long timestamp) { | |
formatDateHeader(new Date(timestamp)) | |
} | |
private static String formatDateHeader(Date date) { | |
HttpHeaderDateFormat.get().format(date) | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/groovy/handling/ErrorHandlingSpec.groovy | |
******************************************************************************** | |
class ErrorHandlingSpec extends RatpackGroovyDslSpec { | |
def "handles 404"() { | |
when: | |
app {} | |
then: | |
get().statusCode == 404 | |
} | |
def "handles internal error"() { | |
when: | |
app { | |
handlers { | |
get { throw new RuntimeException('error here') } | |
} | |
} | |
then: | |
get().statusCode == 500 | |
} | |
def "can handle errors on forked threads"() { | |
given: | |
def errorHandler = new ServerErrorHandler() { | |
void error(Context exchange, Exception exception) { | |
exchange.response.send("Caught: $exception.message") | |
} | |
} | |
when: | |
app { | |
modules { | |
bind ServerErrorHandler, errorHandler | |
} | |
handlers { | |
get { | |
withErrorHandling new Thread({ | |
throw new Exception("thrown in forked thread") | |
}) | |
} | |
} | |
} | |
then: | |
text == "Caught: thrown in forked thread" | |
} | |
def "can use service on forked threads"() { | |
given: | |
def errorHandler1 = new ServerErrorHandler() { | |
void error(Context exchange, Exception exception) { | |
exchange.response.send("1: $exception.message") | |
} | |
} | |
def errorHandler2 = new ServerErrorHandler() { | |
void error(Context exchange, Exception exception) { | |
exchange.response.send("2: $exception.message") | |
} | |
} | |
when: | |
app { | |
modules { | |
bind ServerErrorHandler, errorHandler1 | |
} | |
handlers { | |
get { exchange -> | |
withErrorHandling new Thread({ | |
insert(ServerErrorHandler, errorHandler2, Arrays.asList(new Handler() { | |
@Override | |
void handle(Context context) { | |
throw new Exception("down here") | |
} | |
})) | |
}) | |
} | |
} | |
} | |
then: | |
text == "2: down here" | |
} | |
def "can segment error handlers"() { | |
given: | |
def errorHandler1 = new ServerErrorHandler() { | |
void error(Context exchange, Exception exception) { | |
exchange.response.send("1: $exception.message") | |
} | |
} | |
def errorHandler2 = new ServerErrorHandler() { | |
void error(Context exchange, Exception exception) { | |
exchange.response.send("2: $exception.message") | |
} | |
} | |
when: | |
app { | |
modules { | |
bind ServerErrorHandler, errorHandler1 | |
} | |
handlers { | |
register(ServerErrorHandler, errorHandler2) { | |
get("a") { | |
throw new Exception("1") | |
} | |
} | |
get("b") { | |
throw new Exception("2") | |
} | |
} | |
} | |
then: | |
getText("a") == "2: 1" | |
getText("b") == "1: 2" | |
} | |
def "can use service handler"() { | |
given: | |
def errorHandler = new ServerErrorHandler() { | |
void error(Context exchange, Exception exception) { | |
exchange.response.send("Caught: $exception.message") | |
} | |
} | |
when: | |
app { | |
modules { | |
bind ServerErrorHandler, errorHandler | |
} | |
handlers { | |
get { | |
throw new Exception("thrown") | |
} | |
} | |
} | |
then: | |
text == "Caught: thrown" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/handling/HandlersSpec.groovy | |
******************************************************************************** | |
class HandlersSpec extends RatpackGroovyDslSpec { | |
def "empty chain handler"() { | |
when: | |
app { | |
handlers { | |
chain([]) | |
} | |
} | |
then: | |
get().statusCode == 404 | |
} | |
def "single chain handler"() { | |
when: | |
app { | |
handlers { | |
handler chain( | |
Handlers.get(asHandler { response.send("foo") }) | |
) | |
} | |
} | |
then: | |
text == "foo" | |
} | |
def "multi chain handler"() { | |
when: | |
app { | |
handlers { | |
handler chain( | |
Handlers.get("a", asHandler { response.send("foo") }), | |
Handlers.get("b", asHandler { response.send("bar") }) | |
) | |
} | |
} | |
then: | |
getText("a") == "foo" | |
getText("b") == "bar" | |
} | |
def "default services available"() { | |
when: | |
app { | |
handlers { | |
handler { | |
get(ServerErrorHandler) | |
get(ClientErrorHandler) | |
get(MimeTypes) | |
get(LaunchConfig) | |
get(FileSystemBinding) | |
response.send "ok" | |
} | |
} | |
} | |
then: | |
text == "ok" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/handling/ServiceUsingHandlerSpec.groovy | |
******************************************************************************** | |
class ServiceUsingHandlerSpec extends DefaultRatpackSpec { | |
static class NoHandleMethod extends ServiceUsingHandler {} | |
def "must have handle method"() { | |
when: | |
new NoHandleMethod() | |
then: | |
thrown ServiceUsingHandler.NoSuitableHandleMethodException | |
} | |
static class NoHandleMethodWithContextAsFirstParam extends ServiceUsingHandler { | |
void handle(String foo) {} | |
} | |
def "must have handle method with context as first param"() { | |
when: | |
new NoHandleMethodWithContextAsFirstParam() | |
then: | |
thrown ServiceUsingHandler.NoSuitableHandleMethodException | |
} | |
static class InjectedHandler extends ServiceUsingHandler { | |
@SuppressWarnings(["GrMethodMayBeStatic", "GroovyUnusedDeclaration"]) | |
protected handle(Context exchange, FileSystemBinding fileSystemBinding) { | |
assert fileSystemBinding.is(exchange.get(FileSystemBinding)) | |
exchange.response.send(fileSystemBinding.class.name) | |
} | |
} | |
def "can inject"() { | |
when: | |
app { | |
handlers { | |
handler new InjectedHandler() | |
} | |
} | |
then: | |
text == DefaultFileSystemBinding.class.name | |
} | |
static class Injected2Handler extends ServiceUsingHandler { | |
@SuppressWarnings(["GrMethodMayBeStatic", "GroovyUnusedDeclaration"]) | |
protected handle(Context exchange, FileSystemBinding fileSystemBinding, ServerErrorHandler serverErrorHandler) { | |
assert fileSystemBinding.is(exchange.get(FileSystemBinding)) | |
assert serverErrorHandler.is(exchange.get(ServerErrorHandler)) | |
exchange.response.send(serverErrorHandler.class.name) | |
} | |
} | |
def "can inject more than one"() { | |
when: | |
app { | |
handlers { | |
handler new Injected2Handler() | |
} | |
} | |
then: | |
text == DefaultServerErrorHandler.class.name | |
} | |
static class InjectedBadHandler extends ServiceUsingHandler { | |
@SuppressWarnings(["GrMethodMayBeStatic", "GroovyUnusedDeclaration"]) | |
protected handle(Context exchange, FileSystemBinding fileSystemBinding, Exception notInRegistry) {} | |
} | |
static class MessageServerErrorHandler implements ServerErrorHandler { | |
void error(Context exchange, Exception exception) { | |
exchange.response.status(500).send(exception.message) | |
} | |
} | |
def "error when cant inject"() { | |
when: | |
app { | |
handlers { | |
handler register(ServerErrorHandler, new MessageServerErrorHandler(), new Action<Chain>() { | |
void execute(Chain handlers) { | |
handlers.handler(new InjectedBadHandler()) | |
} | |
}) | |
} | |
} | |
then: | |
text =~ "No object for type 'java.lang.Exception' in registry" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/http/ConcurrentRequestSpec.groovy | |
******************************************************************************** | |
class ConcurrentRequestSpec extends RatpackGroovyDslSpec { | |
def "can serve requests concurrently without mixing up params"() { | |
when: | |
app { | |
handlers { | |
get(":id") { | |
response.send pathTokens.id + ":" + request.queryParams.id | |
} | |
} | |
} | |
and: | |
def threads = 500 | |
def latch = new CountDownLatch(threads) | |
def results = [] | |
threads.times { | |
results << null | |
} | |
startServerIfNeeded() | |
threads.times { i -> | |
Thread.start { | |
try { | |
def text = createRequest().get(toUrl("$i?id=$i")).asString() | |
assert text ==~ "\\d+:\\d+" | |
def (id, value) = text.split(':').collect { it.toInteger() } | |
results[id] = value | |
} finally { | |
latch.countDown() | |
} | |
} | |
} | |
latch.await(30, TimeUnit.SECONDS) | |
then: | |
(0..<threads).each { | |
assert results[it] == it | |
} | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/http/ContentNegotiationSpec.groovy | |
******************************************************************************** | |
class ContentNegotiationSpec extends RatpackGroovyDslSpec { | |
def "can content negotiate"() { | |
when: | |
app { | |
handlers { | |
get { | |
respond byContent. | |
type("application/json") { | |
response.send "json" | |
}. | |
type("text/html") { | |
response.send "html" | |
} | |
} | |
get("noneRegistered") { | |
respond byContent | |
} | |
} | |
} | |
then: | |
request.header("Accept", "application/json;q=0.5,text/html;q=1") | |
text == "html" | |
response.header("Content-Type") == "text/html;charset=UTF-8" | |
response.statusCode == 200 | |
then: | |
request.header("Accept", "application/json,text/html") | |
text == "json" | |
response.header("Content-Type") == "application/json" | |
response.statusCode == 200 | |
then: | |
request.header("Accept", "*") | |
text == "json" | |
then: | |
request.header("Accept", "*/*") | |
text == "json" | |
then: | |
request.header("Accept", "text/*") | |
text == "html" | |
then: | |
request.header("Accept", "") | |
text == "json" | |
then: | |
request.header("Accept", "some/nonsense") | |
text == "" | |
response.statusCode == 406 | |
then: | |
getText("noneRegistered") == "" | |
response.statusCode == 406 | |
} | |
def "by accepts responder mime types"() { | |
setup: | |
"setting up the handler chain" | |
app { | |
handlers { | |
get { | |
respond byContent. | |
json { response.send "json" }. | |
xml { response.send "xml" }. | |
plainText { response.send "text" }. | |
html { response.send "html" } | |
} | |
} | |
} | |
when: | |
"testing json" | |
request.header("Accept", "application/json") | |
then: | |
"the json accept type should be invoked" | |
text == "json" | |
when: | |
"testing xml" | |
request.header("Accept", "application/xml") | |
then: | |
"the xml accept type should be invoked" | |
text == "xml" | |
when: | |
"testing plainText" | |
request.header("Accept", "text/plain") | |
then: | |
"the plain text accept type should be invoked" | |
text == "text" | |
when: | |
"testing html" | |
request.header("Accept", "text/html") | |
then: | |
"the plain text accept type should be invoked" | |
text == "html" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/http/CookiesSpec.groovy | |
******************************************************************************** | |
class CookiesSpec extends RatpackGroovyDslSpec { | |
def "can get and set cookies"() { | |
given: | |
app { | |
handlers { | |
get("get/:name") { | |
response.send request.oneCookie(pathTokens.name) ?: "null" | |
} | |
get("set/:name/:value") { | |
response.cookie(pathTokens.name, pathTokens.value) | |
response.send() | |
} | |
get("clear/:name") { | |
response.expireCookie(pathTokens.name) | |
response.send() | |
} | |
} | |
} | |
when: | |
getText("set/a/1") | |
then: | |
getText("get/a") == "1" | |
when: | |
getText("set/a/2") | |
getText("set/b/1") | |
then: | |
getText("get/a") == "2" | |
getText("get/b") == "1" | |
when: | |
getText("clear/a") | |
then: | |
getText("get/a") == "null" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/http/DefaultMediaTypeSpec.groovy | |
******************************************************************************** | |
class DefaultMediaTypeSpec extends Specification { | |
def "parsing"() { | |
expect: | |
ct(" application/json ").type == "application/json" | |
ct(" application/json ").params.isEmpty() | |
ct(null).type == null | |
ct(null).params.isEmpty() | |
ct(" ").type == null | |
ct(" ").params.isEmpty() | |
ct(" application/json;charset=foo ").params.charset == "foo" | |
ct(" application/json;charset ;foo=bar ").params == [charset: "", foo: "bar"] | |
} | |
def "tostring"() { | |
expect: | |
cts("") == "" | |
cts(" application/json ") == "application/json" | |
cts("application/json;foo=bar") == "application/json;foo=bar" | |
cts("application/json;foo") == "application/json;foo" | |
cts("application/json;a=1 ; b=2") == "application/json;a=1;b=2" | |
} | |
private MediaType ct(s) { | |
DefaultMediaType.get(s) | |
} | |
private String cts(s) { | |
ct(s).toString() | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/http/RequestBodyReadingSpec.groovy | |
******************************************************************************** | |
class RequestBodyReadingSpec extends RatpackGroovyDslSpec { | |
def "can get request body as bytes"() { | |
when: | |
app { | |
handlers { | |
post { | |
response.send new String(request.bytes, "utf8") | |
} | |
} | |
} | |
then: | |
request.body("foo".getBytes("utf8")) | |
postText() == "foo" | |
} | |
def "can get request body as input stream"() { | |
when: | |
app { | |
handlers { | |
post { | |
response.send new String(request.inputStream.bytes, "utf8") | |
} | |
} | |
} | |
then: | |
request.body("foo".getBytes("utf8")) | |
postText() == "foo" | |
} | |
def "can get large request body as bytes"() { | |
given: | |
def string = "a" * 1024 * 9 | |
when: | |
app { | |
handlers { | |
post { | |
response.send new String(request.bytes, "utf8") | |
} | |
} | |
} | |
then: | |
request.body(string.getBytes("utf8")) | |
postText() == string | |
} | |
def "get bytes on get request"() { | |
when: | |
app { | |
handlers { | |
handler { | |
response.send request.bytes.length.toString() | |
} | |
} | |
} | |
then: | |
getText() == "0" | |
postText() == "0" | |
putText() == "0" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/http/RequestParametersSpec.groovy | |
******************************************************************************** | |
class RequestParametersSpec extends RatpackGroovyDslSpec { | |
def "can get query params"() { | |
when: | |
app { | |
handlers { | |
get { | |
response.send request.queryParams.toString() | |
} | |
} | |
} | |
then: | |
getText() == "[:]" && resetRequest() | |
getText("?a=b") == "[a:[b]]" && resetRequest() | |
request { | |
queryParam "a", "b", "c" | |
queryParam "d", "e" | |
} | |
getText() == "[a:[b, c], d:[e]]" && resetRequest() | |
getText("?abc") == "[abc:[]]" && resetRequest() | |
} | |
def "can get form params"() { | |
when: | |
app { | |
handlers { | |
post { | |
response.send request.form.toString() | |
} | |
} | |
} | |
then: | |
postText() == "[:]" && resetRequest() | |
request { | |
param "a", "b" | |
} | |
postText() == "[a:[b]]" && resetRequest() | |
request { | |
param "a", "b", "c" | |
param "d", "e" | |
param "abc" | |
} | |
postText() == "[a:[b, c], d:[e], abc:[]]" && resetRequest() | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/http/SpecifiedContentTypeSpec.groovy | |
******************************************************************************** | |
@Issue("https://github.com/ratpack/ratpack/issues/127") | |
class SpecifiedContentTypeSpec extends RatpackGroovyDslSpec { | |
def "content type can be specified by handler"() { | |
given: | |
app { | |
handlers { | |
get("path") { | |
response.contentType mimeType | |
response.send content | |
} | |
} | |
} | |
when: | |
get("path") | |
then: | |
with(response) { | |
statusCode == OK.code() | |
response.body.asString() == content | |
response.contentType == "$mimeType;charset=UTF-8" | |
} | |
where: | |
content | mimeType | |
"x,y,z" | "text/csv" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/path/PathAndMethodRoutingSpec.groovy | |
******************************************************************************** | |
class PathAndMethodRoutingSpec extends RatpackGroovyDslSpec { | |
def "can use path and method routes"() { | |
when: | |
app { | |
handlers { | |
get("a/b/c") { | |
response.headers.set("X-value", request.query) | |
response.send request.query | |
} | |
prefix(":a/:b") { | |
path(":c/:d") { | |
respond byMethod. | |
post { | |
response.send new LinkedHashMap(allPathTokens).toString() | |
}. | |
put { | |
response.send allPathTokens.collectEntries { [it.key.toUpperCase(), it.value.toUpperCase()] }.toString() | |
} | |
} | |
} | |
} | |
} | |
then: | |
getText("a/b/c?foo=baz") == "foo=baz" | |
resetRequest() | |
postText("1/2/3/4") == "[a:1, b:2, c:3, d:4]" | |
putText("5/6/7/8") == "[A:5, B:6, C:7, D:8]" | |
with(head("a/b/c?head")) { | |
statusCode == 200 | |
getHeader("X-value") == "head" | |
asByteArray().length == 0 | |
} | |
} | |
def "can use method chain"() { | |
when: | |
app { | |
handlers { | |
path("foo") { | |
def prefix = "common" | |
respond byMethod. | |
get { | |
response.send("$prefix: get") | |
}. | |
post { | |
response.send("$prefix: post") | |
} | |
} | |
} | |
} | |
then: | |
getText("foo") == "common: get" | |
postText("foo") == "common: post" | |
put("foo").statusCode == 405 | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/path/PathParamsSpec.groovy | |
******************************************************************************** | |
class PathParamsSpec extends RatpackGroovyDslSpec { | |
def "can parse url params"() { | |
when: | |
app { | |
handlers { | |
get(":a/:b/:c?") { | |
response.send new LinkedHashMap(pathTokens).toString() | |
} | |
} | |
} | |
then: | |
getText("1/2/3") == [a: 1, b: 2, c: 3].toString() | |
getText("1/2") == [a: 1, b: 2].toString() | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/path/PathRoutingSpec.groovy | |
******************************************************************************** | |
class PathRoutingSpec extends RatpackGroovyDslSpec { | |
def "can route by prefix"() { | |
when: | |
app { | |
handlers { | |
prefix("abc") { | |
handler { | |
response.send(get(PathBinding).boundTo) | |
} | |
} | |
} | |
} | |
then: | |
getText("abc/def") == "abc" | |
getText("abc/ghi") == "abc" | |
getText("abc") == "abc" | |
get("ab/def").statusCode == NOT_FOUND.code() | |
} | |
def "can route by nested prefix"() { | |
when: | |
app { | |
handlers { | |
prefix("abc") { | |
prefix("def") { | |
handler { | |
response.send(get(PathBinding).pastBinding) | |
} | |
} | |
} | |
} | |
} | |
then: | |
getText("abc/def/ghi") == "ghi" | |
getText("abc/def/jkl") == "jkl" | |
getText("abc/def") == "" | |
get("abc/de/ghi").statusCode == NOT_FOUND.code() | |
} | |
def "can route by prefix with tokens"() { | |
when: | |
app { | |
handlers { | |
prefix(":a/:b/:c") { | |
handler { | |
def binding = get(PathBinding) | |
response.send("$binding.tokens - $binding.pastBinding") | |
} | |
} | |
} | |
} | |
then: | |
getText("1/2/3/4/5") == "[a:1, b:2, c:3] - 4/5" | |
} | |
def "can route by nested prefix with tokens"() { | |
when: | |
app { | |
handlers { | |
prefix(":a/:b") { | |
prefix(":d/:e") { | |
handler { | |
def binding = get(PathBinding) | |
response.send("$binding.tokens - $binding.allTokens - $binding.pastBinding") | |
} | |
} | |
} | |
} | |
} | |
then: | |
getText("1/2/3/4/5/6") == "[d:3, e:4] - [a:1, b:2, d:3, e:4] - 5/6" | |
} | |
def "can route by exact path"() { | |
when: | |
app { | |
handlers { | |
path("abc") { | |
response.send(get(PathBinding).boundTo) | |
} | |
} | |
} | |
then: | |
getText("abc") == "abc" | |
get("abc/def").statusCode == NOT_FOUND.code() | |
get("ab").statusCode == NOT_FOUND.code() | |
} | |
def "can route by nested exact path"() { | |
when: | |
app { | |
handlers { | |
prefix("abc") { | |
path("def") { | |
response.send(get(PathBinding).boundTo) | |
} | |
} | |
} | |
} | |
then: | |
getText("abc/def") == "def" | |
get("abc/def/ghi").statusCode == NOT_FOUND.code() | |
get("abc/de").statusCode == NOT_FOUND.code() | |
get("abc").statusCode == NOT_FOUND.code() | |
} | |
def "can route by exact path with tokens"() { | |
when: | |
app { | |
handlers { | |
path(":a/:b/:c") { | |
def binding = get(PathBinding) | |
response.send("$binding.tokens - $binding.pastBinding") | |
} | |
} | |
} | |
then: | |
get("1/2/3/4/5").statusCode == NOT_FOUND.code() | |
getText("1/2/3") == "[a:1, b:2, c:3] - " | |
} | |
def "can route by nested exact path with tokens"() { | |
when: | |
app { | |
handlers { | |
prefix(":a/:b") { | |
path(":d/:e") { | |
def binding = get(PathBinding) | |
response.send("$binding.tokens - $binding.allTokens - $binding.pastBinding") | |
} | |
} | |
} | |
} | |
then: | |
getText("1/2/3/4") == "[d:3, e:4] - [a:1, b:2, d:3, e:4] - " | |
get("1/2/3/4/5/6").statusCode == NOT_FOUND.code() | |
} | |
def "can use get handler"() { | |
when: | |
app { | |
handlers { | |
get { | |
response.send("root") | |
} | |
get("a") { | |
response.send("a") | |
} | |
} | |
} | |
then: | |
getText() == "root" | |
getText("a") == "a" | |
get("a/b/c").statusCode == NOT_FOUND.code() | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/registry/ServiceRegistryToStringSpec.groovy | |
******************************************************************************** | |
class ServiceRegistryToStringSpec extends Specification { | |
def "registry to strings show chain"() { | |
when: | |
def root = new RootRegistry(ImmutableList.of(1)) | |
def object1 = new ObjectHoldingChildRegistry(root, 2) | |
def object2 = new ObjectHoldingChildRegistry(object1, 3) | |
def lazy = new LazyChildRegistry(object2, Integer, { 4 } as org.ratpackframework.util.Factory<Integer>) | |
then: | |
lazy.toString() == "LazyChildRegistry{${Integer.name}} -> ObjectServiceRegistry{3} -> ObjectServiceRegistry{2} -> RootRegistry{[1]}" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-core/src/test/groovy/org/ratpackframework/server/BindAddressInContextSpec.groovy | |
******************************************************************************** | |
class BindAddressInContextSpec extends RatpackGroovyDslSpec { | |
def "bind address is available in context"() { | |
when: | |
app { | |
handlers { | |
get("port") { BindAddress bindAddress -> | |
response.send bindAddress.port.toString() | |
} | |
get("host") { BindAddress bindAddress -> | |
response.send bindAddress.host | |
} | |
} | |
} | |
then: | |
getText("port") == server.bindPort.toString() | |
getText("host") == server.bindHost | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-gradle/src/test/groovy/org/ratpackframework/gradle/functional/FunctionalSpec.groovy | |
******************************************************************************** | |
abstract class FunctionalSpec extends Specification { | |
@Rule TemporaryFolder dir | |
static class ExecutedTask { | |
Task task | |
TaskState state | |
} | |
List<ExecutedTask> executedTasks = [] | |
GradleLauncher launcher(String... args) { | |
StartParameter startParameter = GradleLauncher.createStartParameter(args) | |
startParameter.setProjectDir(dir.root) | |
GradleLauncher launcher = GradleLauncher.newInstance(startParameter) | |
executedTasks.clear() | |
launcher.addListener(new TaskExecutionListener() { | |
void beforeExecute(Task task) { | |
getExecutedTasks() << new ExecutedTask(task: task) | |
} | |
void afterExecute(Task task, TaskState taskState) { | |
getExecutedTasks().last().state = taskState | |
taskState.metaClass.upToDate = taskState.skipMessage == "UP-TO-DATE" | |
} | |
}) | |
launcher | |
} | |
BuildResult run(String... args) { | |
def launcher = launcher(*args) | |
def result = launcher.run() | |
result.rethrowFailure() | |
result | |
} | |
File getBuildFile() { | |
makeFile("build.gradle") | |
} | |
File makeFile(String path) { | |
def f = file(path) | |
if (!f.exists()) { | |
def parts = path.split("/") | |
if (parts.size() > 1) { | |
dir.newFolder(*parts[0..-2]) | |
} | |
dir.newFile(path) | |
} | |
f | |
} | |
File file(String path) { | |
def file = new File(dir.root, path) | |
assert file.parentFile.mkdirs() || file.parentFile.exists() | |
file | |
} | |
ExecutedTask task(String name) { | |
executedTasks.find { it.task.name == name } | |
} | |
def setup() { | |
file("settings.gradle") << "rootProject.name = 'test-app'" | |
buildFile << """ | |
ext.RatpackGroovyPlugin = project.class.classLoader.loadClass('${RatpackGroovyPlugin.name}') | |
apply plugin: RatpackGroovyPlugin | |
archivesBaseName = "functional-test" | |
version = "1.0" | |
repositories { | |
maven { url "file://${localRepo.absolutePath}" } | |
jcenter() | |
} | |
""" | |
} | |
def unzip(File source, File destination) { | |
def project = ProjectBuilder.builder().withProjectDir(dir.root).build() | |
project.copy { | |
from project.zipTree(source) | |
into destination | |
} | |
} | |
File getWarFile() { | |
def f = file("build/libs/functional-test-1.0.war") | |
assert f.exists() | |
f | |
} | |
def unpackedWarFile(path) { | |
def unpacked = file("build/unpacked-war") | |
if (!unpacked.exists()) { | |
unzip(warFile, unpacked) | |
} | |
new File(unpacked, path) | |
} | |
File getLocalRepo() { | |
def rootRelative = new File("build/localrepo") | |
rootRelative.directory ? rootRelative : new File(new File(System.getProperty("user.dir")).parentFile, "build/localrepo") | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-gradle/src/test/groovy/org/ratpackframework/gradle/functional/InstallAppSpec.groovy | |
******************************************************************************** | |
class InstallAppSpec extends FunctionalSpec { | |
def "everything goes in the right place"() { | |
given: | |
file("src/ratpack/ratpack.groovy") << """ | |
import static org.ratpackframework.groovy.RatpackScript.ratpack | |
ratpack { | |
handlers { | |
get("") { | |
response.send "foo" | |
} | |
} | |
} | |
""" | |
when: | |
run "installApp" | |
def process = new ProcessBuilder().directory(file("build/install/test-app")).command("bin/test-app").start() | |
process.consumeProcessOutput(System.out, System.err) | |
then: | |
new PollingConditions().within(10) { | |
try { | |
urlText("") == "foo" | |
} catch (ConnectException ignore) { | |
false | |
} | |
} | |
cleanup: | |
process?.destroy() | |
process?.waitFor() | |
} | |
HttpURLConnection url(String path = "") { | |
new URL("http://localhost:5050/$path").openConnection() as HttpURLConnection | |
} | |
String urlText(String path = "") { | |
new URL("http://localhost:5050/$path").text | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-groovy/src/test/groovy/org/ratpackframework/groovy/ExampleRestSpec.groovy | |
******************************************************************************** | |
class ExampleRestSpec extends RatpackGroovyScriptAppSpec { | |
def "get by id"() { | |
given: | |
script """ | |
ratpack { | |
handlers { | |
get { | |
response.send "Yeah!" | |
} | |
} | |
} | |
""" | |
when: | |
get() | |
then: | |
response.statusCode == 200 | |
response.body.asString() == "Yeah!" | |
} | |
def "can verify json"() { | |
given: | |
script """ | |
import groovy.json.JsonOutput | |
import groovy.json.JsonSlurper | |
ratpack { | |
handlers { | |
post { | |
if (!request.contentType.json) { | |
clientError(415) | |
return | |
} | |
respond byContent. | |
type("application/json") { | |
def json = new JsonSlurper().parseText(request.text) | |
def value = json.value | |
response.send "application/json", JsonOutput.toJson([value: value * 2]) | |
} | |
} | |
} | |
} | |
""" | |
when: | |
request { | |
contentType "text/plain" | |
body "foo" | |
} | |
post() | |
then: | |
response.statusCode == 415 | |
when: | |
request { | |
header "Accept", "application/json" | |
contentType "application/json" | |
body '{"value": 1}' | |
} | |
post() | |
then: | |
response.statusCode == 200 | |
response.jsonPath().value == 2 | |
} | |
def "can read request body"() { | |
given: | |
script """ | |
ratpack { | |
handlers { | |
post { | |
response.send(request.text) | |
} | |
} | |
} | |
""" | |
when: | |
request { | |
body "foo" | |
} | |
post() | |
then: | |
response.statusCode == 200 | |
response.body.asString() == "foo" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-groovy/src/test/groovy/org/ratpackframework/groovy/StandaloneScriptSpec.groovy | |
******************************************************************************** | |
class StandaloneScriptSpec extends RatpackGroovyScriptAppSpec { | |
class ScriptBackedService extends AbstractIdleService implements RatpackService { | |
RatpackServer server | |
@Override | |
protected void startUp() throws Exception { | |
def shell = new GroovyShell(getClass().classLoader) | |
def script = shell.parse(StandaloneScriptSpec.this.ratpackFile) | |
StandaloneScriptBacking.captureNext(Util.delegatingAction { | |
server = it | |
}) | |
Thread.start { | |
script.run() | |
} | |
def stopAt = System.currentTimeMillis() + 10000 | |
while (System.currentTimeMillis() < stopAt) { | |
if (server != null) { | |
break | |
} | |
sleep 100 | |
} | |
if (!server) { | |
throw new IllegalStateException("Server did not start") | |
} | |
server.start() | |
} | |
@Override | |
protected void shutDown() throws Exception { | |
server?.stop() | |
} | |
@Override | |
int getBindPort() { | |
server.bindPort | |
} | |
@Override | |
String getBindHost() { | |
server.bindHost | |
} | |
} | |
@Override | |
File getRatpackFile() { | |
file("custom.groovy") | |
} | |
@Override | |
RatpackServer createServer() { | |
def service = new ScriptBackedService() | |
new ServiceBackedServer(service, LaunchConfigBuilder.baseDir(ratpackFile.parentFile).build(new GroovyScriptHandlerFactory())) | |
} | |
def "can execute plain script and reload"() { | |
when: | |
app { | |
script """ | |
ratpack { | |
handlers { | |
get { | |
response.send "foo" | |
} | |
} | |
} | |
""" | |
} | |
then: | |
getText() == "foo" | |
when: | |
script """ | |
ratpack { | |
handlers { | |
get { | |
response.send "bar" | |
} | |
} | |
} | |
""" | |
then: | |
getText() == "bar" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-groovy/src/test/groovy/org/ratpackframework/groovy/handling/BasicGroovyDslSpec.groovy | |
******************************************************************************** | |
class BasicGroovyDslSpec extends RatpackGroovyDslSpec { | |
def "can use special Groovy dsl"() { | |
given: | |
file("public/foo.txt") << "bar" | |
when: | |
app { | |
handlers { | |
get("a") { | |
response.send "a handler" | |
} | |
post("b") { | |
response.send "b handler" | |
} | |
prefix(":first") { | |
get(":second") { | |
response.send new LinkedHashMap<>(allPathTokens).toString() | |
} | |
path("c/:second") { | |
response.send new LinkedHashMap<>(allPathTokens).toString() | |
} | |
} | |
assets("public") | |
} | |
} | |
then: | |
getText("a") == "a handler" | |
get("b").statusCode == 405 | |
postText("b") == "b handler" | |
getText("1/2") == "[first:1, second:2]" | |
getText("foo/c/bar") == "[first:foo, second:bar]" | |
getText("foo.txt") == "bar" | |
} | |
def "can use file method to access file contextually"() { | |
given: | |
file("foo/file.txt") << "foo" | |
file("bar/file.txt") << "bar" | |
when: | |
app { | |
handlers { | |
fileSystem("foo") { | |
get("foo") { | |
response.send file("file.txt").text | |
} | |
} | |
fileSystem("bar") { | |
get("bar") { | |
response.send file("file.txt").text | |
} | |
} | |
} | |
} | |
then: | |
getText("foo") == 'foo' | |
getText("bar") == 'bar' | |
} | |
def "can use method chain"() { | |
when: | |
app { | |
handlers { | |
path("foo") { | |
def prefix = "common" | |
respond byMethod. | |
get { | |
response.send("$prefix: get") | |
}. | |
post { | |
response.send("$prefix: post") | |
} | |
} | |
} | |
} | |
then: | |
getText("foo") == "common: get" | |
postText("foo") == "common: post" | |
put("foo").statusCode == 405 | |
} | |
def "can inject services via closure params"() { | |
when: | |
app { | |
handlers { | |
get("p1") { FileSystemBinding fileSystemBinding -> | |
response.send fileSystemBinding.class.name | |
} | |
get("p2") { FileSystemBinding fileSystemBinding, ServerErrorHandler serverErrorHandler -> | |
response.send serverErrorHandler.class.name | |
} | |
} | |
} | |
then: | |
getText("p1") == DefaultFileSystemBinding.class.name | |
getText("p2") == DefaultServerErrorHandler.class.name | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-groovy/src/test/groovy/org/ratpackframework/groovy/handling/BasicGroovyScriptAppSpec.groovy | |
******************************************************************************** | |
class BasicGroovyScriptAppSpec extends RatpackGroovyScriptAppSpec { | |
def "can use script app"() { | |
given: | |
compileStatic = true | |
when: | |
app { | |
script """ | |
ratpack { | |
handlers { | |
get { | |
getResponse().send("foo") | |
} | |
} | |
} | |
""" | |
} | |
then: | |
getText() == "foo" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-groovy/src/test/groovy/org/ratpackframework/groovy/handling/ChainSubclassParitySpec.groovy | |
******************************************************************************** | |
class ChainSubclassParitySpec extends Specification { | |
def javaType = org.ratpackframework.handling.Chain | |
def groovyType = Chain | |
def "groovy chain subclass overrides universally overrides return type"() { | |
/* | |
We are testing here that the Groovy subclass overrides all of the Java methods | |
in order to specify that it returns the Groovy type | |
*/ | |
given: | |
def javaChainReturningMethods = javaType.getDeclaredMethods().findAll { it.returnType.equals(javaType) } | |
expect: | |
javaChainReturningMethods.each { | |
try { | |
def override = groovyType.getDeclaredMethod(it.name, it.parameterTypes) | |
assert override.returnType == groovyType | |
} catch (NoSuchMethodException ignore) { | |
throw new AssertionError("Chain method $it is not overridden in groovy subclass") | |
} | |
} | |
} | |
def "groovy chain subclass has closure overloads for all handler methods"() { | |
given: | |
def javaChainHandlerAsLastArgMethods = javaType.declaredMethods.findAll { | |
it.parameterTypes.size() > 0 && it.parameterTypes.last() == Handler | |
} | |
expect: | |
javaChainHandlerAsLastArgMethods.each { | |
try { | |
def paramList = it.parameterTypes.toList() | |
paramList[paramList.size() - 1] = Closure | |
def override = groovyType.getDeclaredMethod(it.name, (Class[]) paramList.toArray()) | |
assert override.returnType == Chain | |
assert override.returnType == groovyType | |
} catch (NoSuchMethodException ignore) { | |
throw new AssertionError("Chain method $it is not overridden in groovy subclass") | |
} | |
} | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-groovy/src/test/groovy/org/ratpackframework/groovy/handling/ClosureServiceParametersSpec.groovy | |
******************************************************************************** | |
class ClosureServiceParametersSpec extends RatpackGroovyAppSpec { | |
static class Thing {} | |
static class ThingModule extends AbstractModule { | |
protected void configure() { | |
bind(Thing) | |
} | |
} | |
def "can have global services"() { | |
when: | |
file("templates/foo.html") << "bar" | |
app { | |
modules { | |
register(new ThingModule()) | |
} | |
handlers { Thing thing -> | |
get { | |
response.send thing.class.name | |
} | |
} | |
} | |
then: | |
text == Thing.class.name | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-groovy/src/test/groovy/org/ratpackframework/groovy/handling/DefaultGroovyErrorHandlingSpec.groovy | |
******************************************************************************** | |
class DefaultGroovyErrorHandlingSpec extends RatpackGroovyAppSpec { | |
def "error handler is registered"() { | |
given: | |
app { | |
handlers { | |
get { | |
throw new Exception("!") | |
} | |
} | |
} | |
when: | |
get() | |
then: | |
response.statusCode == 500 | |
response.body.asString().contains "html" | |
} | |
def "error handler is registered next() is not called"() { | |
given: | |
app { | |
handlers { | |
prefix("foo") { | |
handler { | |
throw new Exception("!") | |
} | |
} | |
} | |
} | |
when: | |
get("foo") | |
then: | |
response.statusCode == 500 | |
response.body.asString().contains "html" | |
} | |
def "404 page is used"() { | |
given: | |
app { | |
handlers { | |
get("foo") { | |
response.send("foo") | |
} | |
} | |
} | |
when: | |
get("bar") | |
then: | |
response.statusCode == 404 | |
response.body.asString().contains "html" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-groovy/src/test/groovy/org/ratpackframework/groovy/templating/TemplateRenderingSpec.groovy | |
******************************************************************************** | |
class TemplateRenderingSpec extends RatpackGroovyDslSpec { | |
def setup() { | |
modules << new TemplatingModule() | |
} | |
def "can render template"() { | |
given: | |
file("templates/foo.html") << "a \${model.value} b <% 3.times { %> a <% } %>" | |
when: | |
app { | |
handlers { | |
get { | |
render groovyTemplate("foo.html", value: "bar") | |
} | |
} | |
} | |
then: | |
text == "a bar b a a a " | |
} | |
def "off thread errors are rendered"() { | |
given: | |
when: | |
app { | |
handlers { | |
get { | |
withErrorHandling Thread.start { | |
throw new Exception("nested!") | |
} | |
} | |
} | |
} | |
then: | |
text.contains "<title>java.lang.Exception</title>" | |
} | |
def "can render inner template"() { | |
given: | |
file("templates/outer.html") << "outer: \${model.value}, <% render 'inner.html', value: 'inner' %>" | |
file("templates/inner.html") << "inner: \${model.value}" | |
when: | |
app { | |
handlers { | |
get { | |
render groovyTemplate("outer.html", value: "outer") | |
} | |
} | |
} | |
then: | |
text == "outer: outer, inner: inner" | |
} | |
def "can render inner, inner template"() { | |
given: | |
file("templates/outer.html") << "outer: \${model.value}, <% render 'inner.html', value: 'inner' %>" | |
file("templates/inner.html") << "inner: \${model.value}, <% render 'innerInner.html', value: 1 %>, <% render 'innerInner.html', value: 2 %>, <% render 'innerInner.html', value: 1 %>" | |
file("templates/innerInner.html") << "innerInner: \${model.value}" | |
when: | |
app { | |
handlers { | |
get { | |
render groovyTemplate("outer.html", value: "outer") | |
} | |
} | |
} | |
then: | |
text == "outer: outer, inner: inner, innerInner: 1, innerInner: 2, innerInner: 1" | |
} | |
def "inner template exceptions"() { | |
given: | |
file("templates/outer.html") << "outer: \${model.value}, <% render 'inner.html', value: 'inner' %>" | |
file("templates/inner.html") << "inner: \${model.value}, <% render 'innerInner.html', value: 1 %>, <% render 'innerInner.html', value: 2 %>, <% render 'innerInner.html', value: 1 %>" | |
file("templates/innerInner.html") << "\${throw new Exception(model.value.toString())}" | |
when: | |
app { | |
handlers { | |
get { | |
render groovyTemplate("outer.html", value: "outer") | |
} | |
} | |
} | |
then: | |
text.contains('[innerInner.html] template execution failed') | |
} | |
def "nested templates inherit the outer model"() { | |
given: | |
file("templates/outer.html") << "outer: \${model.a}\${model.b}, <% render 'inner.html', b: 'B' %>" | |
file("templates/inner.html") << "inner: \${model.a}\${model.b}, <% render 'innerInner.html', a: 'A' %>" | |
file("templates/innerInner.html") << "innerInner: \${model.a}\${model.b}" | |
when: | |
app { | |
handlers { | |
get { | |
render groovyTemplate("outer.html", a: "a", b: "b") | |
} | |
} | |
} | |
then: | |
text == "outer: ab, inner: aB, innerInner: AB" | |
} | |
@Unroll | |
"can use render in output section - #template"() { | |
given: | |
file("templates/outer.html") << template | |
file("templates/foo.html") << "foo" | |
when: | |
app { | |
handlers { | |
get { | |
render groovyTemplate("outer.html") | |
} | |
} | |
} | |
then: | |
text == "foo" | |
where: | |
template << ["\${render 'foo.html'}", "<%= render 'foo.html' %>"] | |
} | |
@Unroll | |
"can use render in output section in nested - #template"() { | |
given: | |
file("templates/outer.html") << "<% render 'inner.html' %>" | |
file("templates/inner.html") << template | |
file("templates/foo.html") << "foo" | |
when: | |
app { | |
handlers { | |
get { | |
render groovyTemplate("outer.html") | |
} | |
} | |
} | |
then: | |
text == "foo" | |
where: | |
template << ["\${render 'foo.html'}", "<%= render 'foo.html' %>"] | |
} | |
def "compile error in inner template"() { | |
given: | |
file("templates/outer.html") << "outer: \${model.value}, <% render 'inner.html', value: 'inner' %>" | |
file("templates/inner.html") << "inner: \${model.value.toInteger()}" | |
when: | |
app { | |
modules { | |
get(TemplatingModule).staticallyCompile = true | |
} | |
handlers { | |
get { | |
render groovyTemplate("outer.html", value: "outer") | |
} | |
} | |
} | |
then: | |
text.contains "[inner.html] compilation failure" | |
} | |
def "can get model object via type"() { | |
given: | |
file("templates/template.html") << "value: \${model.get('value', String).toInteger()}" | |
when: | |
app { | |
modules { | |
get(TemplatingModule).staticallyCompile = true | |
} | |
handlers { | |
get { | |
render groovyTemplate("template.html", value: "2") | |
} | |
} | |
} | |
then: | |
text.contains "value: 2" | |
} | |
def "client errors are rendered with the template renderer"() { | |
when: | |
app { | |
handlers { | |
handler { | |
clientError(404) | |
} | |
} | |
} | |
then: | |
text.contains "<title>Not Found</title>" | |
get().statusCode == 404 | |
} | |
def "templates are reloadable in reload mode"() { | |
given: | |
reloadable = true | |
file("templates/t") << "1" | |
when: | |
app { | |
handlers { | |
get { render groovyTemplate("t") } | |
} | |
} | |
then: | |
text == "1" | |
when: | |
sleep 1000 | |
file("templates/t").text = "2" | |
then: | |
text == "2" | |
} | |
def "templates are not reloadable in reload mode"() { | |
given: | |
reloadable = false | |
file("templates/t") << "1" | |
when: | |
app { | |
handlers { | |
get { render groovyTemplate("t") } | |
} | |
} | |
then: | |
text == "1" | |
when: | |
file("templates/t").text = "2" | |
then: | |
text == "1" | |
} | |
def "templates are reloadable if reloading is forced"() { | |
given: | |
file("templates/t") << "1" | |
when: | |
app { | |
modules { | |
get(TemplatingModule).reloadable = true | |
} | |
handlers { | |
get { render groovyTemplate("t") } | |
} | |
} | |
then: | |
text == "1" | |
when: | |
sleep 1000 | |
file("templates/t").text = "2" | |
then: | |
text == "2" | |
} | |
def "content type by template extension"() { | |
when: | |
file("templates/t.html") << "1" | |
file("templates/t.xml") << "1" | |
file("templates/dir/t.html") << "1" | |
file("templates/dir/t.xml") << "1" | |
file("templates/dir/t") << "1" | |
app { | |
handlers { | |
handler { | |
render groovyTemplate(request.path, request.queryParams.type) | |
} | |
} | |
} | |
then: | |
get("t.html").contentType == "text/html;charset=UTF-8" | |
get("t.xml").contentType == "application/xml" | |
get("dir/t.html").contentType == "text/html;charset=UTF-8" | |
get("dir/t.xml").contentType == "application/xml" | |
get("dir/t").contentType == "application/octet-stream" | |
get("t.xml?type=foo/bar").contentType == "foo/bar" | |
get("dir/t.xml?type=foo/bar").contentType == "foo/bar" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-groovy-test/src/test/groovy/org/ratpackframework/groovy/test/remote/RemoteControlUsageSpec.groovy | |
******************************************************************************** | |
class RemoteControlUsageSpec extends RatpackGroovyDslSpec { | |
void setup() { | |
other.put("remoteControl.enabled", "true") | |
} | |
@javax.inject.Singleton | |
static class ValueHolder { | |
String value = "initial" | |
} | |
def "can access application internals"() { | |
when: | |
app { | |
modules { | |
register new RemoteControlModule() | |
bind ValueHolder | |
} | |
} | |
handlers { | |
get { ValueHolder valueHolder -> | |
response.send valueHolder.value | |
} | |
} | |
and: | |
def remote = new RemoteControl(applicationUnderTest) | |
then: | |
text == "initial" | |
when: | |
remote.exec { registry.get(ValueHolder).value = "changed" } | |
then: | |
text == "changed" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-groovy-test/src/test/groovy/org/ratpackframework/groovy/test/remote/RemoteControlUsageSpec.groovy | |
******************************************************************************** | |
class RemoteControlUsageSpec extends RatpackGroovyDslSpec { | |
void setup() { | |
other.put("remoteControl.enabled", "true") | |
} | |
@javax.inject.Singleton | |
static class ValueHolder { | |
String value = "initial" | |
} | |
def "can access application internals"() { | |
when: | |
app { | |
modules { | |
register new RemoteControlModule() | |
bind ValueHolder | |
} | |
} | |
handlers { | |
get { ValueHolder valueHolder -> | |
response.send valueHolder.value | |
} | |
} | |
and: | |
def remote = new RemoteControl(applicationUnderTest) | |
then: | |
text == "initial" | |
when: | |
remote.exec { registry.get(ValueHolder).value = "changed" } | |
then: | |
text == "changed" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-guice/src/test/groovy/org/ratpackframework/guice/GuiceBootstrappingSpec.groovy | |
******************************************************************************** | |
class GuiceBootstrappingSpec extends RatpackGroovyDslSpec { | |
static class ServiceOne { | |
String name | |
} | |
static class ServiceTwo { | |
String name | |
} | |
@Override | |
Transformer<Module, Injector> createInjectorFactory() { | |
Injector parentInjector = createInjector(new AbstractModule() { | |
@Override | |
protected void configure() { | |
bind(ServiceOne).toInstance(new ServiceOne(name: "parent")) | |
} | |
}) | |
Guice.childInjectorFactory(parentInjector) | |
} | |
def "parent injector objects are available"() { | |
when: | |
app { | |
modules { | |
bind ServiceTwo, new ServiceTwo(name: "child") | |
} | |
handlers { | |
get { ServiceOne one, ServiceTwo two -> | |
response.send "$one.name:$two.name" | |
} | |
} | |
} | |
then: | |
text == "parent:child" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-guice/src/test/groovy/org/ratpackframework/guice/InjectedHandlersSpec.groovy | |
******************************************************************************** | |
class InjectedHandlersSpec extends RatpackGroovyDslSpec { | |
static class Injectable { | |
String name | |
} | |
static class InjectedHandler implements Handler { | |
Injectable injectable | |
@Inject | |
InjectedHandler(Injectable injectable) { | |
this.injectable = injectable | |
} | |
@Override | |
void handle(Context exchange) { | |
exchange.response.send(injectable.name) | |
} | |
} | |
def "can use injected handlers"() { | |
given: | |
def nameValue = "foo" | |
when: | |
app { | |
modules { | |
assert launchConfig != null | |
register(new AbstractModule() { | |
@Override | |
protected void configure() { | |
bind(Injectable).toInstance(new Injectable(name: nameValue)) | |
} | |
}) | |
} | |
handlers { | |
handler registry.get(InjectedHandler) | |
} | |
} | |
then: | |
text == nameValue | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-guice/src/test/groovy/org/ratpackframework/guice/ModuleRegistryBindingsSpec.groovy | |
******************************************************************************** | |
class ModuleRegistryBindingsSpec extends RatpackGroovyDslSpec { | |
static interface Type1 {} | |
static class Type1Impl1 implements Type1 {} | |
static class Type1Impl2 implements Type1 {} | |
static interface Type2 {} | |
static class Type2Impl1 implements Type2 {} | |
static class Type2Impl2 implements Type2 {} | |
static class Type2Provider implements Provider<Type2> { | |
Type2 get() { | |
new Type2Impl2() | |
} | |
} | |
static class SomeType {} | |
def "can bind via module registry"() { | |
when: | |
app { | |
modules { | |
// direct bindings always override module bindings | |
bind SomeType | |
bind Type1, Type1Impl2 | |
provider Type2, Type2Provider | |
// regardless of module registration order | |
register new AbstractModule() { | |
protected void configure() { | |
bind(Type1).to(Type1Impl1) | |
bind(Type2).to(Type2Impl1) | |
} | |
} | |
} | |
handlers { | |
get("classDirect") { SomeType someType -> | |
response.send someType.class.name | |
} | |
get("publicType") { Type1 someType -> | |
response.send someType.class.name | |
} | |
get("provider") { Type2 someType -> | |
response.send someType.class.name | |
} | |
} | |
} | |
then: | |
getText("classDirect") == SomeType.name | |
getText("publicType") == Type1Impl2.name | |
getText("provider") == Type2Impl2.name | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-guice/src/test/groovy/org/ratpackframework/guice/RendererBindingsSpec.groovy | |
******************************************************************************** | |
class RendererBindingsSpec extends RatpackGroovyDslSpec { | |
static class IntRenderer extends ByTypeRenderer<Integer> { | |
public IntRenderer() { | |
super(Integer) | |
} | |
@Override | |
void render(Context context, Integer object) { | |
context.response.send("text/integer", object.toString()) | |
} | |
} | |
static class StringRenderer extends ByTypeRenderer<String> { | |
public StringRenderer() { | |
super(String) | |
} | |
@Override | |
void render(Context context, String object) { | |
context.response.send("text/string", object.toString()) | |
} | |
} | |
def "bound renderers are usable"() { | |
when: | |
app { | |
modules { | |
register new AbstractModule() { | |
protected void configure() { | |
bind(IntRenderer) | |
bind(StringRenderer) | |
bind(ServerErrorHandler).to(PrintingServerErrorHandler) | |
} | |
} | |
} | |
handlers { | |
get("int") { | |
render 1 | |
} | |
get("string") { | |
render "abc" | |
} | |
get("none") { | |
render new LinkedList() | |
} | |
} | |
} | |
then: | |
with(get("int")) { | |
body.asString() == "1" | |
contentType == "text/integer;charset=UTF-8" | |
} | |
with(get("string")) { | |
body.asString() == "abc" | |
contentType == "text/string;charset=UTF-8" | |
} | |
with(get("none")) { | |
statusCode == 500 | |
body.asString().contains(NoSuchRendererException.name) | |
} | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-handlebars/src/test/groovy/org/ratpackframework/handlebars/HandlebarsTemplateRenderingSpec.groovy | |
******************************************************************************** | |
class HandlebarsTemplateRenderingSpec extends RatpackGroovyDslSpec { | |
@Unroll | |
void 'can render a handlebars template from #scenario'() { | |
given: | |
other = otherConfig | |
file(filePath) << '{{key}}' | |
when: | |
app { | |
modules { | |
register new HandlebarsModule(templatesPath: templatesPath) | |
} | |
handlers { | |
get { | |
render handlebarsTemplate('simple', key: 'it works!') | |
} | |
} | |
} | |
then: | |
text == 'it works!' | |
where: | |
scenario | templatesPath | filePath | otherConfig | |
'default path' | null | 'handlebars/simple.hbs' | [:] | |
'path set in module' | 'custom' | 'custom/simple.hbs' | [:] | |
'path set in config' | null | 'fromConfig/simple.hbs' | ['handlebars.templatesPath': "fromConfig"] | |
} | |
@Unroll | |
void 'can configure loader suffix via #scenario'() { | |
given: | |
other = otherConfig | |
file('handlebars/simple.hbs') << '{{this}}' | |
when: | |
app { | |
modules { | |
register new HandlebarsModule(templatesSuffix: templatesSuffix) | |
} | |
handlers { | |
get { | |
render handlebarsTemplate('simple.hbs', 'it works!') | |
} | |
} | |
} | |
then: | |
text == 'it works!' | |
where: | |
scenario | templatesSuffix | otherConfig | |
'module' | '' | [:] | |
'config' | null | ['handlebars.templatesSuffix': ''] | |
} | |
void 'missing templates are handled'() { | |
given: | |
file('handlebars').mkdir() | |
app { | |
modules { | |
register new HandlebarsModule() | |
} | |
handlers { | |
get { | |
render handlebarsTemplate('simple', key: 'it works!') | |
} | |
} | |
} | |
when: | |
get() | |
then: | |
response.statusCode == INTERNAL_SERVER_ERROR.code() | |
} | |
void 'helpers can be registered'() { | |
given: | |
file('handlebars/helper.hbs') << '{{test}}' | |
when: | |
app { | |
modules { | |
register new HandlebarsModule() | |
bind TestHelper | |
} | |
handlers { | |
get { | |
render handlebarsTemplate('helper') | |
} | |
} | |
} | |
then: | |
text == 'from helper' | |
} | |
void 'content types are based on file type but can be overriden'() { | |
given: | |
file('handlebars/simple.hbs') << '{{this}}' | |
file('handlebars/simple.json.hbs') << '{{this}}' | |
file('handlebars/simple.html.hbs') << '{{this}}' | |
when: | |
app { | |
modules { | |
register new HandlebarsModule() | |
} | |
handlers { | |
handler { | |
render handlebarsTemplate(request.path, 'content types', request.queryParams.type) | |
} | |
} | |
} | |
then: | |
get("simple").contentType == "application/octet-stream" | |
get("simple.json").contentType == "application/json" | |
get("simple.html").contentType == "text/html;charset=UTF-8" | |
get("simple.html?type=application/octet-stream").contentType == "application/octet-stream" | |
} | |
} | |
class TestHelper implements NamedHelper { | |
String name = 'test' | |
CharSequence apply(Object context, Options options) throws IOException { | |
'from helper' | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-jackson/src/test/groovy/org/ratpackframework/jackson/JacksonRenderingSpec.groovy | |
******************************************************************************** | |
class JacksonRenderingSpec extends RatpackGroovyDslSpec { | |
static class User { | |
String username | |
String password | |
} | |
def "can render json"() { | |
when: | |
app { | |
modules { | |
register new JacksonModule() | |
} | |
handlers { | |
get { | |
render json(new User(username: "foo", password: "bar")) | |
} | |
} | |
} | |
then: | |
get().jsonPath().get("username") == "foo" | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-remote/src/test/groovy/org/ratpackframework/remote/RemoteControlSpec.groovy | |
******************************************************************************** | |
class RemoteControlSpec extends RatpackGroovyDslSpec { | |
void appWithRemoteControl() { | |
app { | |
modules { | |
register new RemoteControlModule() | |
} | |
} | |
} | |
void appWithEnabledRemoteControl() { | |
other['remoteControl.enabled'] = 'true' | |
appWithRemoteControl() | |
} | |
RemoteControl getRemote() { | |
startServerIfNeeded() | |
new RemoteControl(new HttpTransport("http://localhost:${server.bindPort}/$DEFAULT_REMOTE_CONTROL_PATH")) | |
} | |
void 'by default the endpoint is not enabled'() { | |
given: | |
appWithRemoteControl() | |
expect: | |
post(DEFAULT_REMOTE_CONTROL_PATH).statusCode == NOT_FOUND.code() | |
} | |
void 'only posts are allowed'() { | |
given: | |
appWithEnabledRemoteControl() | |
expect: | |
get(DEFAULT_REMOTE_CONTROL_PATH).statusCode == METHOD_NOT_ALLOWED.code() | |
head(DEFAULT_REMOTE_CONTROL_PATH).statusCode == METHOD_NOT_ALLOWED.code() | |
} | |
void 'only requests that contain groovy-remote-control-command are allowed'() { | |
given: | |
appWithEnabledRemoteControl() | |
expect: | |
post(DEFAULT_REMOTE_CONTROL_PATH).statusCode == UNSUPPORTED_MEDIA_TYPE.code() | |
} | |
void 'only requests that accept groovy-remote-control-result are allowed'() { | |
given: | |
appWithEnabledRemoteControl() | |
when: | |
request.header(HttpHeaders.Names.CONTENT_TYPE, RemoteControlHandler.REQUEST_CONTENT_TYPE) | |
request.header(HttpHeaders.Names.ACCEPT, 'text/html') | |
then: | |
post(DEFAULT_REMOTE_CONTROL_PATH).statusCode == NOT_ACCEPTABLE.code() | |
} | |
@Unroll | |
void 'sending a simple command - #scenario'() { | |
given: | |
app { | |
modules { | |
register new RemoteControlModule(path: modulePath) | |
} | |
} | |
other = ['remoteControl.enabled': 'true'] + otherConfig | |
and: | |
startServerIfNeeded() | |
def remoteControl = new RemoteControl(new HttpTransport("http://localhost:${server.bindPort}/$path")) | |
expect: | |
remoteControl { 1 + 2 } == 3 | |
where: | |
scenario | path | modulePath | otherConfig | |
'default path' | DEFAULT_REMOTE_CONTROL_PATH | null | [:] | |
'path set in module' | 'custom' | 'custom' | [:] | |
'path set in config' | 'fromConfig' | null | ['remoteControl.path': 'fromConfig'] | |
} | |
void 'registry is available in command context'() { | |
given: | |
appWithEnabledRemoteControl() | |
other.test = 'it works' | |
expect: | |
//from guice | |
remote.exec { registry.get(LaunchConfig).other.test } == 'it works' | |
//from root registry | |
remote.exec { registry.get(DefaultFileSystemBinding) != null } | |
//created just in time | |
remote.exec { registry.get(FileRenderer) != null } | |
} | |
void 'endpoint is also enabled if reloading is enabled'() { | |
given: | |
reloadable = true | |
appWithRemoteControl() | |
expect: | |
remote.exec { 1 + 2 } == 3 | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-session/src/test/groovy/org/ratpackframework/session/SessionSpec.groovy | |
******************************************************************************** | |
class SessionSpec extends RatpackGroovyDslSpec { | |
def setup() { | |
modules << new SessionModule() | |
modules << new MapSessionsModule(10, 5) | |
} | |
def "can use session"() { | |
when: | |
app { | |
handlers { | |
get(":v") { | |
response.send get(Session).id | |
} | |
} | |
} | |
then: | |
getText("a") == getText("b") | |
} | |
def "can store session vars"() { | |
when: | |
app { | |
handlers { | |
get("") { | |
def store = get(SessionStorage) | |
response.send store.value.toString() | |
} | |
get("set/:value") { | |
def store = get(SessionStorage) | |
store.value = pathTokens.value | |
response.send store.value.toString() | |
} | |
} | |
} | |
and: | |
getText("set/foo") == "foo" | |
then: | |
getText() == "foo" | |
} | |
def "can invalidate session vars"() { | |
when: | |
app { | |
handlers { | |
get("") { | |
def store = get(SessionStorage) | |
response.send store.value ?: "null" | |
} | |
get("set/:value") { | |
def store = get(SessionStorage) | |
store.value = pathTokens.value | |
response.send store.value ?: "null" | |
} | |
get("invalidate") { | |
get(Session).terminate() | |
response.send() | |
} | |
get("size") { | |
response.send get(SessionStore).size().toString() | |
} | |
} | |
} | |
and: | |
getText("set/foo") | |
then: | |
getText() == "foo" | |
getText("size") == "1" | |
when: | |
getText("invalidate") | |
then: | |
getText() == "null" | |
getText("size") == "1" | |
} | |
def "sessions are created on demand"() { | |
when: | |
app { | |
handlers { | |
get { | |
response.send get(SessionStore).size().toString() | |
} | |
} | |
} | |
then: | |
getText() == "0" | |
when: | |
app { | |
handlers { | |
get { | |
get(SessionStorage) | |
response.send get(SessionStore).size().toString() | |
} | |
} | |
} | |
then: | |
getText() == "1" | |
} | |
def "session cookies are only set when needed"() { | |
when: | |
app { | |
handlers { | |
get("foo") { | |
response.send("foo") | |
} | |
get("bar") { | |
get(SessionStorage) // just retrieve | |
response.send("bar") | |
} | |
} | |
} | |
then: | |
get("foo").cookies().isEmpty() | |
get("bar").cookies().JSESSIONID != null | |
// null because the session id is already set | |
get("bar").cookies().JSESSIONID == null | |
} | |
} | |
******************************************************************************** | |
ratpack/ratpack-site/src/test/groovy/org/ratpackframework/site/SiteSmokeSpec.groovy | |
******************************************************************************** | |
class SiteSmokeSpec extends ScriptAppSpec { | |
def "Check Site Index"() { | |
when: | |
get("index.html") | |
then: | |
response.statusCode == 200 | |
response.body.asString().contains('<title>Ratpack: A toolkit for JVM web applications</title>') | |
} | |
def "Check Site /"() { | |
when: | |
get("") | |
then: | |
response.statusCode == 200 | |
response.body.asString().contains('<title>Ratpack: A toolkit for JVM web applications</title>') | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment