|
Lift Framework example source code file (TestFramework.scala)
The Lift Framework TestFramework.scala source code/* * Copyright 2008-2011 WorldWide Conferencing, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.liftweb package http package testing import net.liftweb.util.Helpers._ import net.liftweb.util._ import net.liftweb.json._ import JsonDSL._ import net.liftweb.common._ import scala.xml._ import scala.xml.Utility.trim import java.util.{Map => JavaMap, Set => JavaSet, Iterator => JavaIterator, List => JavaList} import java.util.regex.Pattern import java.io.IOException import org.apache.commons.httpclient._ import org.apache.commons.httpclient.cookie._ import methods._ import java.io.OutputStream import org.apache.commons.httpclient.auth.AuthScope trait ToResponse { self: BaseGetPoster => type ResponseType = TestResponse implicit def responseCapture(fullUrl: String, httpClient: HttpClient, getter: HttpMethodBase): ResponseType = { val ret: ResponseType = try { (baseUrl + fullUrl, httpClient.executeMethod(getter)) match { case (server, responseCode) => val respHeaders = slurpApacheHeaders(getter.getResponseHeaders) new HttpResponse(baseUrl, responseCode, getter.getStatusText, respHeaders, for {st <- Box !! getter.getResponseBodyAsStream bytes <- tryo(readWholeStream(st)) } yield bytes, httpClient) } } catch { case e: IOException => new CompleteFailure(baseUrl + fullUrl, Full(e)) } finally { getter.releaseConnection } ret } } trait ToBoxTheResponse { self: BaseGetPoster => type ResponseType = Box[TheResponse] implicit def responseCapture(fullUrl: String, httpClient: HttpClient, getter: HttpMethodBase): Box[TheResponse] = { val ret = try { (baseUrl + fullUrl, httpClient.executeMethod(getter)) match { case (server, responseCode) => val respHeaders = slurpApacheHeaders(getter.getResponseHeaders) Full(new TheResponse(baseUrl, responseCode, getter.getStatusText, respHeaders, for {st <- Box !! getter.getResponseBodyAsStream bytes <- tryo(readWholeStream(st)) } yield bytes, httpClient)) } } catch { case e: IOException => Failure(baseUrl + fullUrl, Full(e), Empty) } finally { getter.releaseConnection } ret } } trait GetPoster extends BaseGetPoster with ToResponse /** * A trait that wraps the Apache Commons HTTP client and supports GET and POST */ trait BaseGetPoster { type ResponseType /** * The base URL for all requests */ def baseUrl: String protected def slurpApacheHeaders(in: Array[Header]): Map[String, List[String]] = { val headerSet: List[(String, String)] = for (e <- in.toList) yield (e.getName -> e.getValue) headerSet.foldLeft[Map[String, List[String]]](Map.empty)((acc, e) => acc + (e._1 -> (e._2 :: acc.getOrElse(e._1, Nil)))) } /** * Perform an HTTP GET * * @param url - the URL to append to the baseUrl * @param headers - any additional headers to include with the request * @param faux_params - the request parameters to include with the request */ def get(url: String, httpClient: HttpClient, headers: List[(String, String)], faux_params: (String, Any)*) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType): ResponseType = { val params = faux_params.toList.map(x => (x._1, x._2.toString)) val fullUrl = url + (params.map(v => urlEncode(v._1) + "=" + urlEncode(v._2)).mkString("&") match {case s if s.length == 0 => ""; case s => "?" + s}) val getter = new GetMethod(baseUrl + fullUrl) getter.getParams().setCookiePolicy(CookiePolicy.RFC_2965) for ((name, value) <- headers) getter.setRequestHeader(name, value) capture(fullUrl, httpClient, getter) } /** * Perform an HTTP DELETE * * @param url - the URL to append to the baseUrl * @param headers - any additional headers to include with the request * @param faux_params - the request parameters to include with the request */ def delete(url: String, httpClient: HttpClient, headers: List[(String, String)], faux_params: (String, Any)*) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType): ResponseType = { val params = faux_params.toList.map(x => (x._1, x._2.toString)) val fullUrl = url + (params.map(v => urlEncode(v._1) + "=" + urlEncode(v._2)).mkString("&") match {case s if s.length == 0 => ""; case s => "?" + s}) val getter = new DeleteMethod(baseUrl + fullUrl) getter.getParams().setCookiePolicy(CookiePolicy.RFC_2965) for ((name, value) <- headers) getter.setRequestHeader(name, value) capture(fullUrl, httpClient, getter) } /** * Perform an HTTP POST * * @param url - the URL to append to the baseUrl * @param headers - any additional headers to include with the request * @param faux_params - the request parameters to include with the request */ def post(url: String, httpClient: HttpClient, headers: List[(String, String)], faux_params: (String, Any)*) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType): ResponseType = { val params = faux_params.toList.map(x => (x._1, x._2.toString)) val poster = new PostMethod(baseUrl + url) poster.getParams().setCookiePolicy(CookiePolicy.RFC_2965) for ((name, value) <- headers) poster.setRequestHeader(name, value) for ((name, value) <- params) poster.setParameter(name, value) capture(url, httpClient, poster) } implicit def xmlToRequestEntity(body: NodeSeq): RequestEntity = new RequestEntity { val bytes = body.toString.getBytes("UTF-8") def getContentLength() = bytes.length def getContentType() = "text/xml; charset=utf-8" def isRepeatable() = true def writeRequest(out: OutputStream) { out.write(bytes) } } implicit def jsonToRequestEntity(body: JValue): RequestEntity = new RequestEntity { val bytes = compact(render(body)).toString.getBytes("UTF-8") def getContentLength() = bytes.length def getContentType() = "application/json" def isRepeatable() = true def writeRequest(out: OutputStream) { out.write(bytes) } } /** * Perform an HTTP POST with an XML body * * @param url - the URL to append to the baseUrl * @param headers - any additional headers to include with the request * @param body - the xml to post */ def post[RT](url: String, httpClient: HttpClient, headers: List[(String, String)], body: RT) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType, bodyToRequestEntity: RT => RequestEntity): ResponseType = { val poster = new PostMethod(baseUrl + url) poster.getParams().setCookiePolicy(CookiePolicy.RFC_2965) for ((name, value) <- headers) poster.setRequestHeader(name, value) poster.setRequestEntity(bodyToRequestEntity(body)) capture(url, httpClient, poster) } /** * Perform an HTTP POST with a pile of bytes in the body * * @param url - the URL to append to the baseUrl * @param headers - any additional headers to include with the request * @param body - the pile of bytes to POST to the target server * @param contentType - the content type of the pile of bytes */ def post(url: String, httpClient: HttpClient, headers: List[(String, String)], body: Array[Byte], contentType: String) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType): ResponseType = { val poster = new PostMethod(baseUrl + url) poster.getParams().setCookiePolicy(CookiePolicy.RFC_2965) for ((name, value) <- headers) poster.setRequestHeader(name, value) poster.setRequestEntity(new RequestEntity { private val bytes = body def getContentLength() = bytes.length def getContentType() = contentType def isRepeatable() = true def writeRequest(out: OutputStream) { out.write(bytes) } }) capture(url, httpClient, poster) } /** * Perform an HTTP PUT * * @param url - the URL to append to the baseUrl * @param headers - any additional headers to include with the request */ def put(url: String, httpClient: HttpClient, headers: List[(String, String)]) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType): ResponseType = { val poster = new PutMethod(baseUrl + url) poster.getParams().setCookiePolicy(CookiePolicy.RFC_2965) for ((name, value) <- headers) poster.setRequestHeader(name, value) capture(url, httpClient, poster) } /** * Perform an HTTP PUT with an XML body * * @param url - the URL to append to the baseUrl * @param headers - any additional headers to include with the request * @param body - the xml to post */ def put[RT](url: String, httpClient: HttpClient, headers: List[(String, String)], body: RT) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType, bodyToRequestEntity: RT => RequestEntity): ResponseType = { val poster = new PutMethod(baseUrl + url) poster.getParams().setCookiePolicy(CookiePolicy.RFC_2965) for ((name, value) <- headers) poster.setRequestHeader(name, value) poster.setRequestEntity(bodyToRequestEntity(body)) capture(url, httpClient, poster) } /** * Perform an HTTP PUT with a pile of bytes in the body * * @param url - the URL to append to the baseUrl * @param headers - any additional headers to include with the request * @param body - the pile of bytes to POST to the target server * @param contentType - the content type of the pile of bytes */ def put(url: String, httpClient: HttpClient, headers: List[(String, String)], body: Array[Byte], contentType: String) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType): ResponseType = { val poster = new PutMethod(baseUrl + url) poster.getParams().setCookiePolicy(CookiePolicy.RFC_2965) for ((name, value) <- headers) poster.setRequestHeader(name, value) poster.setRequestEntity(new RequestEntity { private val bytes = body def getContentLength() = bytes.length def getContentType() = contentType def isRepeatable() = true def writeRequest(out: OutputStream) { out.write(bytes) } }) capture(url, httpClient, poster) } } /** * A trait for reporting failures */ trait ReportFailure { def fail(msg: String): Nothing } trait GetPosterHelper { self: BaseGetPoster => /** * Create the HTTP client for a new get/post request */ def theHttpClient: HttpClient /** * Perform an HTTP GET with a newly minted httpClient * * @param url the URL to make the request on * @param params the parameters to pass */ def get(url: String, params: (String, Any)*) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType): ResponseType = get(url, theHttpClient, Nil, params: _*)(capture) /** * Perform an HTTP DELETE with a newly minted httpClient * * @param url the URL to make the request on * @param params the parameters to pass */ def delete(url: String, params: (String, Any)*) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType): ResponseType = delete(url, theHttpClient, Nil, params: _*)(capture) /** * Perform an HTTP POST with a newly minted httpClient * * @param url the URL to make the request on * @param params the parameters to pass */ def post(url: String, params: (String, Any)*) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType): ResponseType = post(url, theHttpClient, Nil, params: _*)(capture) /** * Perform an HTTP POST with a newly minted httpClient * * @param url the URL to make the request on * @param xml the XML to POST to the server */ def post[RT](url: String, xml: RT) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType, bodyToRequestEntity: RT => RequestEntity): ResponseType = post(url, theHttpClient, Nil, xml)(capture, bodyToRequestEntity) /** * Perform an HTTP POST with a newly minted httpClient * * @param url the URL to make the request on * @param body the bytes to POST to the server * @param contentType the content type of the message */ def post(url: String, body: Array[Byte], contentType: String) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType): ResponseType = post(url, theHttpClient, Nil, body, contentType)(capture) /** * Perform an HTTP PUT with a newly minted httpClient * * @param url the URL to make the request on * @param xml the XML to PUT to the server */ def put[RT](url: String, xml: RT) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType, bodyToRequestEntity: RT => RequestEntity): ResponseType = put(url, theHttpClient, Nil, xml)(capture, bodyToRequestEntity) /** * Perform an HTTP POST with a newly minted httpClient * * @param url the URL to make the request on * @param body the bytes to POST to the server * @param contentType the content type of the message */ def put(url: String, body: Array[Byte], contentType: String) (implicit capture: (String, HttpClient, HttpMethodBase) => ResponseType): ResponseType = put(url, theHttpClient, Nil, body, contentType)(capture) } /** * Mix this trait into your test so you can make HTTP requests on a target */ trait TestKit extends ClientBuilder with GetPoster with GetPosterHelper { /** * The base URL for all GET and POST requests */ def baseUrl: String class TestHandler(res: TestResponse) { def then(f: TestResponse => TestResponse): TestResponse = f(res) def also(f: TestResponse => Any): TestResponse = {f(res); res} } implicit def reqToHander(in: TestResponse): TestHandler = new TestHandler(in) } trait ClientBuilder { /** * Create the HTTP client for a new get/post request */ def theHttpClient: HttpClient = buildNoAuthClient /** * Create a new HTTP client that does not do any form of AUTH */ def buildNoAuthClient = new HttpClient(new SimpleHttpConnectionManager(false)) /** * Create a new HTTP client that does BASIC AUTH with username/pwd */ def buildBasicAuthClient(name: String, pwd: String) = { val ret = new HttpClient(new SimpleHttpConnectionManager(false)) val defaultcreds = new UsernamePasswordCredentials(name, pwd) ret.getState().setCredentials(AuthScope.ANY, defaultcreds) ret } } /** * Mix this trait into your test so you can make HTTP requests on a target */ trait RequestKit extends ClientBuilder with BaseGetPoster with GetPosterHelper with ToBoxTheResponse { /** * The base URL for all GET and POST requests */ def baseUrl: String } /** * A legacy test framework */ trait TestFramework extends TestKit { // def runner: TestRunner def tests: List[Item] def buildRunner: TestRunner /** * Create the base HTTP client */ override def theHttpClient: HttpClient = defaultHttpClient lazy val defaultHttpClient = buildNoAuthClient // protected lazy val httpClient = new HttpClient(new MultiThreadedHttpConnectionManager) def fork(cnt: Int)(f: Int => Any) { val threads = for (t <- (1 to cnt).toList) yield { val th = new Thread(new Runnable {def run {f(t)}}) th.start th } def waitAll(in: List[Thread]) { in match { case Nil => case x :: xs => x.join; waitAll(xs) } } waitAll(threads) } } object TestHelpers { /** * Get the function name given a particular comet actor name * * @param cometName the name (default prefix) for the comet actor * @param body the body of the response * * @return the name of the JSON function associated with the Comet actor */ def jsonFuncForCometName(cometName: String, body: String): Box[String] = { val p = Pattern.compile("""JSON Func """ + cometName + """ \$\$ ([Ff][^ ]*)""") val m = p.matcher(body) if (m.find) Full(m.group(1)) else Empty } /** * Given an HTML page, find the list of "lift_toWatch" names and values * These can be fed back into a comet request * * @param body the page body returned from an HTTP request * * @return a list of the "to watch" tokens and the last update tokens */ def toWatchFromPage(body: String): List[(String, String)] = { val p = Pattern.compile("""lift_toWatch[ ]*\=[ ]*\{([^}]*)\}""") val rp = new REMatcher(body, p) val p2 = Pattern.compile("""'([^']*)'\: ([0-9]*)""") for (it <- rp.capture; val _ = println("Captured: " + it); val _ = println("Does match: " + p2.matcher(it).find); val q = new REMatcher(it, p2); em <- q.eachFound) yield (em(1), em(2)) } /** * Given the body of a Comet response, parse for updates "lift_toWatch" values * and update the current sequence to reflect any updated values * * @param old the old toWatch sequence * @param body the body of the comet response * * @return the updated sequences */ def toWatchUpdates(old: Seq[(String, String)], body: String): Seq[(String, String)] = { val p = Pattern.compile("""lift_toWatch\[\'([^\']*)\'] \= \'([0-9]*)""") val re = new REMatcher(body, p) val np = re.eachFound.foldLeft(Map(old: _*))((a, b) => a + ((b(1), b(2)))) np.iterator.toList } def getCookie(headers: List[(String, String)], respHeaders: Map[String, List[String]]): Box[String] = { val ret = (headers.filter {case ("Cookie", _) => true; case _ => false}. map(_._2) ::: respHeaders.get("Set-Cookie").toList.flatMap(x => x)) match { case Nil => Empty case "" :: Nil => Empty case "" :: xs => Full(xs.mkString(",")) case xs => Full(xs.mkString(",")) } ret } type CRK = JavaList[String] implicit def jitToIt[T](in: JavaIterator[T]): Iterator[T] = new Iterator[T] { def next: T = in.next def hasNext = in.hasNext } private def snurpHeaders(in: JavaMap[String, CRK]): Map[String, List[String]] = { def morePulling(e: JavaMap.Entry[String, CRK]): (String, List[String]) = { e.getValue match { case null => (e.getKey, Nil) case a => (e.getKey, a.iterator.toList) } } Map(in.entrySet.iterator.toList.filter(e => (e ne null) && (e.getKey != null)).map(e => morePulling(e)): _*) } } /** * A response returned from an HTTP request. Responses can be chained and tested in a for comprehension: * <pre> * * implicit val * * for { * login <- post("/api/login", "user" -> "me", "pwd" -> "me") !@ "Failed to log in" * info <- login.get("/api/info") if info.bodyAsString must_== "My Info" * moreInfo <- info.post("/api/moreInfo", <info>Some Info</info>) * } moreInfoheaders("X-MyInfo") must_== List("hello", "goodbye") * </pre> */ trait Response { type SelfType type FuncType /** * The XML for the body */ def xml: Box[Elem] /** * The response headers */ def headers: Map[String, List[String]] /** * Test the response as a 200. If the response is not a 200, call the errorFunc with the msg * * @param msg the String to report as an error * @param errorFunc the error reporting thing. */ def !@(msg: => String)(implicit errorFunc: ReportFailure): SelfType /** * Test that the server gave a response. If the server failed to respond, call the errorFunc with the msg * * @param msg the String to report as an error * @param errorFunc the error reporting thing. */ def !(msg: => String)(implicit errorFunc: ReportFailure): SelfType /** * Test that the server gave a particular response code. If the response is not a 200, call the errorFunc with the msg * * @param msg the String to report as an error * @param errorFunc the error reporting thing. */ def !(code: Int, msg: => String)(implicit errorFunc: ReportFailure): SelfType /** * Test that the server response contains a particular node anywhere in the xml * with the exact attributes and children. * If the response does not contain valid xml or does not contain the exact node, * call the errorFunc with the msg. * * @param node the XML node to search for in the response * @param msg the String to report as an error * @param errorFunc the error reporting thing. */ def \\(node: Node, msg: => String)(implicit errorFunc: ReportFailure): SelfType /** * Test that the server response contains a node with a particular label anywhere in the xml. * If the response does not contain valid xml or does not contain the node, * call the errorFunc with the msg * * @param label the label for the XML node to search for in the response * @param msg the String to report as an error * @param errorFunc the error reporting thing. */ def \\(label: String, msg: => String)(implicit errorFunc: ReportFailure): SelfType /** * Test that the server response does not contain a particular node anywhere in the xml * with the exact attributes and children. * If the response does contain valid xml and does contain the exact node, * call the errorFunc with the msg. * * @param node the XML node to search for in the response * @param msg the String to report as an error * @param errorFunc the error reporting thing. */ def !\\(node: Node, msg: => String)(implicit errorFunc: ReportFailure): SelfType /** * Test that the server response does not contain a node with a particular label anywhere in the xml. * If the response does contain valid xml and does contain the node, * call the errorFunc with the msg * * @param label the label for the XML node to search for in the response * @param msg the String to report as an error * @param errorFunc the error reporting thing. */ def !\\(label: String, msg: => String)(implicit errorFunc: ReportFailure): SelfType /** * Test that the server response contains a particular node as a direct child * with the exact attributes and children. * If the response does not contain valid xml or does not contain the exact node, * call the errorFunc with the msg. * * @param node the XML node to search for in the response * @param msg the String to report as an error * @param errorFunc the error reporting thing. */ def \(node: Node, msg: => String)(implicit errorFunc: ReportFailure): SelfType /** * Test that the server response contains a node with a particular label as a direct child. * If the response does not contain valid xml or does not contain the node, * call the errorFunc with the msg * * @param label the label for the XML node to search for in the response * @param msg the String to report as an error * @param errorFunc the error reporting thing. */ def \(label: String, msg: => String)(implicit errorFunc: ReportFailure): SelfType /** * Test that the server response does not contain a particular node as a direct child * with the exact attributes and children. * If the response does contain valid xml and does contain the exact node, * call the errorFunc with the msg. * * @param node the XML node to search for in the response * @param msg the String to report as an error * @param errorFunc the error reporting thing. */ def !\(node: Node, msg: => String)(implicit errorFunc: ReportFailure): SelfType /** * Test that the server response does not contain a node with a particular label as a direct child. * If the response does contain valid xml and does contain the node, * call the errorFunc with the msg * * @param label the label for the XML node to search for in the response * @param msg the String to report as an error * @param errorFunc the error reporting thing. */ def !\(label: String, msg: => String)(implicit errorFunc: ReportFailure): SelfType /** * the Response has a foreach method for chaining in a for comprehension */ def foreach(f: FuncType => Unit): Unit /** * the Response has a filter method for chaining in a for comprehension. Note that the filter method does *NOT* have * to return a Boolean, any expression (e.g., an assertion) */ def filter(f: FuncType => Unit): FuncType } /** * The response to an HTTP request, as long as the server responds with *SOMETHING* * */ class HttpResponse(baseUrl: String, code: Int, msg: String, headers: Map[String, List[String]], body: Box[Array[Byte]], theHttpClient: HttpClient) extends BaseResponse(baseUrl, code, msg, headers, body, theHttpClient) with ToResponse with TestResponse { } /** * The response to an HTTP request, as long as the server responds with *SOMETHING* * */ class TheResponse(baseUrl: String, code: Int, msg: String, headers: Map[String, List[String]], body: Box[Array[Byte]], theHttpClient: HttpClient) extends BaseResponse(baseUrl, code, msg, headers, body, theHttpClient) with ToBoxTheResponse { type SelfType = TheResponse } trait TestResponse extends Response { override type SelfType = HttpResponse override type FuncType = HttpResponse } /** * The response to an HTTP request, as long as the server responds with *SOMETHING* * */ abstract class BaseResponse(override val baseUrl: String, val code: Int, val msg: String, override val headers: Map[String, List[String]], val body: Box[Array[Byte]], val theHttpClient: HttpClient) extends Response with BaseGetPoster with GetPosterHelper { private object FindElem { def unapply(in: NodeSeq): Option[Elem] = in match { case e: Elem => Some(e) case d: Document => unapply(d.docElem) case g: Group => unapply(g.nodes) case n: Text => None case sn: SpecialNode => None case n: NodeSeq => val ns: Seq[Node] = n val x: Seq[Elem] = ns.flatMap(v => unapply(v)) x.headOption case _ => None } } /** * Get the body of the response as XML */ override lazy val xml: Box[Elem] = for { b <- body nodeSeq <- PCDataXmlParser(new java.io.ByteArrayInputStream(b)) xml <- (nodeSeq.toList match { case (x: Elem) :: _ => Full(x) case _ => Empty }) } yield xml /** * The content type header of the response */ lazy val contentType: String = headers.filter {case (name, value) => name equalsIgnoreCase "content-type"}.toList.headOption.map(_._2.head) getOrElse "" /** * The response body as a UTF-8 encoded String */ lazy val bodyAsString = for { b <- body } yield new String(b, "UTF-8") def !@(msg: => String)(implicit errorFunc: ReportFailure): SelfType = if (code == 200) this.asInstanceOf[SelfType] else {errorFunc.fail(msg)} def !(msg: => String)(implicit errorFunc: ReportFailure): SelfType = this.asInstanceOf[SelfType] def !(code: Int, msg: => String)(implicit errorFunc: ReportFailure): SelfType = if (this.code != code) errorFunc.fail(msg) else this.asInstanceOf[SelfType] def xmlMatch(findFunc: Elem => NodeSeq, filterFunc: Node => Boolean): Boolean = xml.toList flatMap (theXml => findFunc(theXml)) exists ( n => filterFunc(trim(n))) def getOrFail(success: Boolean, msg: String, errorFunc: ReportFailure) = if (success) this.asInstanceOf[SelfType] else errorFunc.fail(msg) def \\(node: Node, msg: => String)(implicit errorFunc: ReportFailure): SelfType = getOrFail(xmlMatch(_ \\ node.label, _ == trim(node)), msg, errorFunc) def \\(label: String, msg: => String)(implicit errorFunc: ReportFailure): SelfType = getOrFail(xmlMatch(_ \\ label, _ => true), msg, errorFunc) def !\\(node: Node, msg: => String)(implicit errorFunc: ReportFailure): SelfType = getOrFail(!xmlMatch(_ \\ node.label, _ == trim(node)), msg, errorFunc) def !\\(label: String, msg: => String)(implicit errorFunc: ReportFailure): SelfType = getOrFail(!xmlMatch(_ \\ label, _ => true), msg, errorFunc) def \(node: Node, msg: => String)(implicit errorFunc: ReportFailure): SelfType = getOrFail(xmlMatch(_ \ node.label, _ == trim(node)), msg, errorFunc) def \(label: String, msg: => String)(implicit errorFunc: ReportFailure): SelfType = getOrFail(xmlMatch(_ \ label, _ => true), msg, errorFunc) def !\(node: Node, msg: => String)(implicit errorFunc: ReportFailure): SelfType = getOrFail(!xmlMatch(_ \ node.label, _ == trim(node)), msg, errorFunc) def !\(label: String, msg: => String)(implicit errorFunc: ReportFailure): SelfType = getOrFail(!xmlMatch(_ \ label, _ => true), msg, errorFunc) def foreach(f: FuncType => Unit): Unit = f(this.asInstanceOf[FuncType]) def filter(f: FuncType => Unit): FuncType = { val st = this.asInstanceOf[FuncType] f(st) st } } class CompleteFailure(val serverName: String, val exception: Box[Throwable]) extends TestResponse { override def toString = serverName + (exception.map(e => " Exception: " + e.getMessage) openOr "") def headers: Map[String, List[String]] = throw (exception openOr new java.io.IOException("HTTP Failure")) def xml: Box[Elem] = throw (exception openOr new java.io.IOException("HTTP Failure")) def !@(msg: => String)(implicit errorFunc: ReportFailure): SelfType = errorFunc.fail(msg) def !(msg: => String)(implicit errorFunc: ReportFailure): SelfType = errorFunc.fail(msg) def !(code: Int, msg: => String)(implicit errorFunc: ReportFailure): SelfType = errorFunc.fail(msg) def \\(node: Node, msg: => String)(implicit errorFunc: ReportFailure): SelfType = errorFunc.fail(msg) def \\(label: String, msg: => String)(implicit errorFunc: ReportFailure): SelfType = errorFunc.fail(msg) def !\\(node: Node, msg: => String)(implicit errorFunc: ReportFailure): SelfType = errorFunc.fail(msg) def !\\(label: String, msg: => String)(implicit errorFunc: ReportFailure): SelfType = errorFunc.fail(msg) def \(node: Node, msg: => String)(implicit errorFunc: ReportFailure): SelfType = errorFunc.fail(msg) def \(label: String, msg: => String)(implicit errorFunc: ReportFailure): SelfType = errorFunc.fail(msg) def !\(node: Node, msg: => String)(implicit errorFunc: ReportFailure): SelfType = errorFunc.fail(msg) def !\(label: String, msg: => String)(implicit errorFunc: ReportFailure): SelfType = errorFunc.fail(msg) def foreach(f: HttpResponse => Unit): Unit = throw (exception openOr new java.io.IOException("HTTP Failure")) def filter(f: HttpResponse => Unit): HttpResponse = throw (exception openOr new java.io.IOException("HTTP Failure")) } Other Lift Framework examples (source code examples)Here is a short list of links related to this Lift Framework TestFramework.scala source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.