Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala?rev=736864&view=auto ============================================================================== --- incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala (added) +++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala Thu Jan 22 16:26:46 2009 @@ -0,0 +1,129 @@ +/** + * Copyright 2008-2009 WorldWide Conferencing, LLC + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.esme.snippet + +import org.apache.esme._ +import model._ +import actor._ + +import net.liftweb._ +import http._ +import js._ +import JsCmds._ +import JE._ +import util._ +import Helpers._ + +import scala.xml.{NodeSeq, Text, Node} + +object JsonPoster extends SessionVar(S.buildJsonFunc{ + case JsonCmd("post", _, map: Map[String, Any], _) => + for (msgObj <- map.get("msg"); + msg <- Box.isA(msgObj, classOf[String]).map(_.trim) if msg.length > 0; + tagObj <- map.get("tags"); + tags <- Box.isA(tagObj, classOf[String]); + user <- User.currentUser) { + + val replyTo = map.get("reply-to").map(toLong) match { + case Some(x) if x > 0L => Full(x) + case _ => Empty + } + + Distributor ! + Distributor.UserCreatedMessage(user.id, msg, + Tag.split(tags), + millis, + Empty, + "web", + replyTo) + + } + Noop + + case _ => Noop + } +) + +class UserSnip extends DispatchSnippet { + def dispatch: DispatchIt = + Map("name" -> userName _, + "postScript" -> postScript _, + "followers" -> followers _, + "following" -> following _, + "loginForm" -> loginForm _, + "loggedIn" -> loggedInFilter _) + + def loggedInFilter(in: NodeSeq): NodeSeq = { + val lookFor = if (User.loggedIn_?) "in" else "out" + + (<foo>{in}</foo> \ lookFor).toList. + filter(_.prefix == "logged"). + map(_.child).firstOption.getOrElse(NodeSeq.Empty) + } + + def userFmt(u: User): Node = + <li><a href={"/user/"+urlEncode(u.nickname.is)}>{u.niceName}</a> {u.firstName} {u.lastName}</li> + + def calcUser: Box[User] = + S.attr("userId").flatMap(s => User.find(toLong(s))) or User.currentUser + + def followers(in: NodeSeq): NodeSeq = + <ul> + { + calcUser.toList.flatMap(_.followers.map(userFmt)) + } + </ul> + + def following(in: NodeSeq): NodeSeq = + <ul> + { + calcUser.toList.flatMap(_.following.map(userFmt)) + } + </ul> + + def loginForm(in: NodeSeq): NodeSeq = + if (User.loggedIn_?) NodeSeq.Empty + else User.loginForm + + + def userName(in: NodeSeq) = { + if (User.currentUser.map(_.needsChange_?) openOr false) + S.redirectTo("/user_mgt/edit") + + Text(User.currentUser.map(_.wholeName) openOr "") + } + + def postScript(in: NodeSeq): NodeSeq = + <xml:group> + {Script(JsonPoster.is._2)} + {Script(Function("post_msg", List(), + JsonPoster.is._1("post", + JsObj("msg" -> ValById("textdude"), + "tags" -> ValById("tagdude"), + "reply-to" -> JsVar("currentConvNumber"))) & + SetValById("textdude", "") & + SetValById("tagdude", "") & + JsRaw("clearReplyTo();") + )) + } + </xml:group> +}
Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/.keep URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/.keep?rev=736864&view=auto ============================================================================== (empty) Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/ActionView.scala URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/ActionView.scala?rev=736864&view=auto ============================================================================== --- incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/ActionView.scala (added) +++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/ActionView.scala Thu Jan 22 16:26:46 2009 @@ -0,0 +1,174 @@ +package org.apache.esme.view + +/** + * Copyright 2008-2009 WorldWide Conferencing, LLC + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import net.liftweb._ +import http._ +import js._ +import JE._ +import JsCmds._ +import SHtml._ +import util._ +import Helpers._ +import sitemap._ +import mapper._ +import Loc._ + +import org.apache.esme._ +import model._ + +import scala.xml.{NodeSeq} + +object ActionView { + def loggedIn_? = User.loggedIn_? + + val ifIsLoggedIn = If(loggedIn_? _, "You must be logged in") + + val menuItems = + Menu(Loc("actionMgt", List("action_view", "index"), "Action Management", ifIsLoggedIn)) :: + Nil +} + +class ActionView extends LiftView { + def dispatch = Map("index" -> index _) + + + def index() = + for (user <- User.currentUser) yield { + val spanName = "TokenSpan" + val theName = "theName" + val theAction = "theAction" + val theTest = "theTest" + + var testText = "" + var nameText = "" + + def redisplayActions: JsCmd = SetHtml(spanName, displayActions) + def saveIt(actionText: String): JsCmd = { + + val toSave = Action.create.name(nameText).user(user) + DB.use(toSave.connectionIdentifier) { + ignore => + val act: Box[List[FieldError]] = + for (a1 <- toSave.setAction(actionText); + a2 <- a1.setTest(testText)) + yield a2.validate + + act match { + case Full(Nil) => + toSave.save + S.notice("Action added") + redisplayActions & + SetValById(theName, "") & SetValById(theAction, "") & + SetValById(theTest, "") + + case Full(xs) => S.error(xs); Noop + case Failure(msg, _, _) => S.error(msg) ; Noop + case _ => Noop + } + } + } + + def displayActions: NodeSeq = + Action.findAll(By(Action.user, user), By(Action.removed, false), + OrderBy(Action.id, Ascending)) match { + case Nil => Nil + case xs => + <table> + <tr> + <td>Name</td> + <td>Enabled</td> + <td>Test</td> + <td>Action</td> + <td>Remove</td> + </tr> + { + xs.map(at => + <tr> + <td>{at.name}</td> + <td>Enabled: {ajaxCheckbox(!at.disabled, e => {at.disabled(!e).save; Noop})}</td> + <td><pre>{at.testText}</pre></td> + <td><pre>{at.actionText}</pre></td> + <td> + {SHtml.ajaxButton("Remove", () => {at.removed(true).save ; redisplayActions})} + </td> + </tr>) + } + </table> + } + + <lift:surround with="default" at="content"> + + Manage your Actions items: <br/> + <span id={spanName}> + { + displayActions + } + </span> + + { + ajaxForm( + <xml:group> + <table> + <tr><td colspan="3">New Action</td></tr> + <tr> + <td>Name</td> + <td>{text("", nameText = _) % ("id" -> theName)}</td> + </tr> + <tr> + <td>Test</td> + <td>{textarea("", testText = _) % ("id" -> theTest)}</td> + <td> + @foo -- sender is @foo<br /> + day = (0,1) -- sent on Sunday or Monday<br/> + #moo -- contains the #moo tag<br/> + 50% -- success 50% of the time<br/> + @foo & 50% -- half the time, something sent by @foo<br/> + login -- user has logged in<br/> + followed -- user is being followed<br/> + unfollowed -- user is being unfollowed<br/> + profile -- user changed profile<br/> + every N mins -- repeat action, N is an integer + </td> + </tr> + + <tr> + <td>Action</td> + <td>{textarea("", saveIt) % ("id" -> theAction)}</td> + <td> + filter -- not put in your timeline<br /> + resend -- sends the message to all your followers<br /> + mailto:[email protected] -- sends the message to [email protected]<br/> + http://foo.com/message/in -- HTTP post, %s expands to message<br/> + atom:http://blog.com/feed.atom -- posts new messages from Atom feed<br/> + rss:http://blog.com/feed.rss -- posts new messages from RSS feed + </td> + </tr> + <input type="submit" value="Add" /> + </table> + </xml:group> + ) + } + + </lift:surround> + } +} Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Auth.scala URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Auth.scala?rev=736864&view=auto ============================================================================== --- incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Auth.scala (added) +++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Auth.scala Thu Jan 22 16:26:46 2009 @@ -0,0 +1,104 @@ +package org.apache.esme.view + +/** + * Copyright 2008-2009 WorldWide Conferencing, LLC + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import net.liftweb._ +import http._ +import js._ +import JE._ +import JsCmds._ +import SHtml._ +import util._ +import Helpers._ +import sitemap._ +import Loc._ + +import org.apache.esme._ +import model._ + +import scala.xml.{NodeSeq} + +object Auth { + def loggedIn_? = User.loggedIn_? + + val ifIsLoggedIn = If(loggedIn_? _, "You must be logged in") + + val menuItems = + Menu(Loc("authToken", List("auth", "index"), "Manage Tokens", ifIsLoggedIn)) :: + Nil +} + +class Auth extends LiftView { + def dispatch = Map("index" -> index _) + + def index() = + for (user <- User.currentUser) yield { + val spanName = "TokenSpan" + val theInput = "theInput" + def redisplayTokens: JsCmd = SetHtml(spanName, displayTokens) + + def addAuthToken(desc: String): JsCmd = { + desc.trim match { + case x if x.length < 3 => S.error("Description too short") + case x => AuthToken.create.description(x).user(user).saveMe + S.notice("New token added") + } + + redisplayTokens & SetValById(theInput, "") + } + + def displayTokens: NodeSeq = + user.authTokens match { + case Nil => Nil + case xs => + <ul> + { + xs.map(at => <li>{at.description} token: {at.uniqueId} + {SHtml.ajaxButton("Revoke", + () => {at.delete_! + redisplayTokens})}</li>) + } + </ul> + } + + <lift:surround with="default" at="content"> + + Manage your external application authentication tokens: <br/> + <span id={spanName}> + { + displayTokens + } + </span> + + { + ajaxForm( + <xml:group> + Create a new Authentication Token.<br /> + Description: {text("", addAuthToken) % ("id" -> theInput)} + <input type="submit" value="Add" /> + </xml:group> + ) + } + + </lift:surround> + } +} Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Track.scala URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Track.scala?rev=736864&view=auto ============================================================================== --- incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Track.scala (added) +++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/Track.scala Thu Jan 22 16:26:46 2009 @@ -0,0 +1,107 @@ +package org.apache.esme.view + +/** + * Copyright 2008-2009 WorldWide Conferencing, LLC + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import net.liftweb._ +import http._ +import js._ +import JE._ +import JsCmds._ +import SHtml._ +import util._ +import Helpers._ +import sitemap._ +import mapper._ +import Loc._ + +import org.apache.esme._ +import model._ + +import scala.xml.{NodeSeq} + +object Track { + def loggedIn_? = User.loggedIn_? + + val ifIsLoggedIn = If(loggedIn_? _, "You must be logged in") + + val menuItems = + Menu(Loc("trackMgt", List("track", "index"), "Item Tracking", ifIsLoggedIn)) :: + Nil +} + +class Track extends LiftView { + def dispatch = Map("index" -> index _) + //{ + //case "index" => index +//} + + def index() = + for (user <- User.currentUser) yield { + val spanName = "TokenSpan" + val theInput = "theInput" + def redisplayTracking: JsCmd = SetHtml(spanName, displayTracking) + + def addTrack(what: String): JsCmd = { + what.trim match { + case x if x.length < 3 => S.error("Too short") + case x => Tracking.create.regex(x).user(user).saveMe + S.notice("Now tracking "+x) + } + + redisplayTracking & SetValById(theInput, "") + } + + def displayTracking: NodeSeq = + Tracking.findAll(By(Tracking.user, user), By(Tracking.removed, false), + OrderBy(Tracking.id, Ascending)) match { + case Nil => Nil + case xs => + <ul> + { + xs.map(at => <li>{at.pattern} Enabled: {ajaxCheckbox(!at.disabled, e => {at.disabled(!e).save; Noop})} + {SHtml.ajaxButton("Remove", () => {at.removed(true).save ; redisplayTracking})}</li>) + } + </ul> + } + + <lift:surround with="default" at="content"> + + Manage your tracking items: <br/> + <span id={spanName}> + { + displayTracking + } + </span> + + { + ajaxForm( + <xml:group> + Track something new.<br /> + What? {text("", addTrack) % ("id" -> theInput)} + <input type="submit" value="Add" /> + </xml:group> + ) + } + + </lift:surround> + } +} Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/UserView.scala URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/UserView.scala?rev=736864&view=auto ============================================================================== --- incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/UserView.scala (added) +++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/view/UserView.scala Thu Jan 22 16:26:46 2009 @@ -0,0 +1,256 @@ +package org.apache.esme.view + +/** + * Copyright 2008-2009 WorldWide Conferencing, LLC + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import net.liftweb._ +import http._ +import js._ +import JE._ +import JsCmds._ +import SHtml._ +import util._ +import Helpers._ +import sitemap._ +import mapper._ +import Loc._ + +import org.apache.esme._ +import model._ +import lib._ + +import scala.xml.{NodeSeq, Text, Elem} + +import java.util.logging._ + +object UserView extends LiftView /* with MsgFormat */ { + val logger: Logger = Logger.getLogger("org.apache.esme.view") + logger.setLevel(Level.INFO) + def loggedIn_? = User.loggedIn_? + + val ifIsLoggedIn = If(loggedIn_? _, "You must be logged in") + + val menuItems = + Menu(Loc("userView", List("user_view", "index"), "View User", Hidden)) :: + Nil + + implicit def fToO(in: () => NodeSeq): Box[() => NodeSeq] = Full(in) + implicit def fToO2(in: Elem): Box[NodeSeq] = Full(in) + + val dispatch = + Map("index" -> index _, + "tag" -> displayTag _, + "search" -> search _, + "all" -> allUsers _, + "conversation" -> conversation _) + + def conversation(): Box[NodeSeq] = { + val cid = S.param("cid").map(toLong).openOr(-1L) + + val msgs = Message.findAndPrime(By(Message.conversation, cid), + OrderBy(Message.id, Ascending)) + + val replyMap = msgs.foldLeft[Map[Long, List[Message]]](Map.empty){ + case (map, msg) => msg.replyTo.can match { + case Full(rt) => map + (rt -> (msg :: map.getOrElse(rt, Nil))) + case _ => map + } + } + + val start = msgs.firstOption.toList + + def show(what: List[Message]): NodeSeq = { + what match { + case Nil => Text("") + case _ => + <ul> + { + what.zipWithIndex.map{ + case (m, idx) => + <span id={"m_"+idx}> + {Script(OnLoad(JsFunc("displayMessages", JsArray(m.asJs), "m_"+idx).cmd)) + } + </span> + } + } + </ul> + } + } + + <lift:surround with="default" at="content"> + <div> + <fieldset> + <legend>Conversation</legend> + { + show(start) + } + </fieldset> + </div> + + </lift:surround> + } + + def index(): Box[NodeSeq] = + (<lift:surround with="default" at="content"> + { + val ui = for (uid <- S.param("uid"); + user <- User.findFromWeb(uid)) yield { + def updateFollow: JsCmd = SetHtml("following", followOrNot) + + def followOrNot: NodeSeq = { + User.currentUser match { + case Full(u) if u != user => + if (u.following_?(user)) + ajaxButton("Unfollow", () => {u.unfollow(user); updateFollow}) + else ajaxButton("Follow", () => {u.follow(user); updateFollow}) + + case _ => <xml:group /> + } + } + + <div> + <div id="tabs" class="b-view tab1"> + <dl class="messages"> + <dt class="caption">{user.niceName}'s Timeline + <span id="following">{followOrNot}</span></dt> + <dd> + { + val lst: List[Message] = + Mailbox.mostRecentMessagesFor(user.id, 50).map(_._1) + // user.latestMessages(50) openOr Nil + lst.zipWithIndex.map{ + case (m, idx) => + <span id={"m2_"+idx}> + { + Script(OnLoad(JsFunc("displayMessages", JsArray(m.asJs), "m2_"+idx).cmd)) + } + </span> + } + } + </dd> + </dl> + + <dl class="tagclouds"> + <dt class="caption">{user.niceName}'s Messages</dt> + + <dd class="b-clouds"> + { + val lst: List[Message] = + Message.findAll(By(Message.author, user), MaxRows(50), OrderBy(Message.id, Descending)) + lst.zipWithIndex.map{ + case (m, idx) => + <span id={"m3_"+idx}> + { + Script(OnLoad(JsFunc("displayMessages", JsArray(m.asJs), "m3_"+idx).cmd)) + } + </span> + } + } + </dd> + </dl> + <dl class="contacts"> + <dt class="caption"> + Contacts + </dt> + + <dd class="b-contacts" style="height: 240px; overflow: auto"> + Following: + <lift:UserSnip.following userId={user.id.toString}/> + </dd> + <dd class="b-contacts" style="height: 240px; overflow: auto"> + Followers: + <lift:UserSnip.followers userId={user.id.toString}/> + </dd> + </dl> + </div> + </div> + } + ui openOr (<span>User Not Found</span>) + } + </lift:surround>) + + def search(): Box[NodeSeq] = + for (user <- User.currentUser; + term <- S.param("term")) yield + <lift:surround with="default" at="content"> + <div> + <fieldset> + <legend>Search: {term}</legend> + <ul> + { + val lst: List[Message] = Message.search(term, user.following, 50) + lst.zipWithIndex.map{ + case (m, idx) => + <span id={"m4_"+idx}> + { + Script(OnLoad(JsFunc("displayMessages", JsArray(m.asJs), "m4_"+idx).cmd)) + } + </span> + } + } + </ul> + </fieldset> + </div> + </lift:surround> + + def displayTag(): Box[NodeSeq] = + (<lift:surround with="default" at="content"> + { + val ui = for (tagText <- S.param("tag").map(_.trim); + tag <- Tag.find(By(Tag.name, tagText))) yield { + val lst = tag.findMessages() + + (<div> + <fieldset> + <legend>{tag.name}</legend> + <ul> + { + lst.zipWithIndex.map{ + case (m, idx) => + <span id={"m5_"+idx}> + { + Script(OnLoad(JsFunc("displayMessages", JsArray(m.asJs), "m5_"+idx).cmd)) + } + </span> + } + } + </ul> + </fieldset> + </div>) + } + ui openOr (<span>Tag Not Found</span>) + } + </lift:surround>) + + def allUsers(): Box[NodeSeq] = + <lift:surround with="default" at="content"> + <fieldset> + <legend>Users</legend> + <ul> + { + User.findAll(OrderBy(User.nickname, Ascending)). + map(u => <li><a href={"/user/"+urlEncode(u.nickname.is)}>{u.niceName}</a> {u.firstName} {u.lastName}</li>) + } + </ul> + </fieldset> + </lift:surround> + +} Added: incubator/esme/trunk/server/src/test/scala/org/apache/esme/AppTest.scala URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/test/scala/org/apache/esme/AppTest.scala?rev=736864&view=auto ============================================================================== --- incubator/esme/trunk/server/src/test/scala/org/apache/esme/AppTest.scala (added) +++ incubator/esme/trunk/server/src/test/scala/org/apache/esme/AppTest.scala Thu Jan 22 16:26:46 2009 @@ -0,0 +1,50 @@ +/** + * Copyright 2008-2009 WorldWide Conferencing, LLC + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.esme; + +import _root_.junit.framework._; +import Assert._; + +object AppTest { + def suite: Test = { + val suite = new TestSuite(classOf[AppTest]); + suite + } + + def main(args : Array[String]) { + _root_.junit.textui.TestRunner.run(suite); + } +} + +/** + * Unit test for simple App. + */ +class AppTest extends TestCase("app") { + + /** + * Rigourous Tests :-) + */ + def testOK() = assertTrue(true); + //def testKO() = assertTrue(false); + + +} Added: incubator/esme/trunk/server/src/test/scala/org/apache/esme/lib/MsgParseTest.scala URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/test/scala/org/apache/esme/lib/MsgParseTest.scala?rev=736864&view=auto ============================================================================== --- incubator/esme/trunk/server/src/test/scala/org/apache/esme/lib/MsgParseTest.scala (added) +++ incubator/esme/trunk/server/src/test/scala/org/apache/esme/lib/MsgParseTest.scala Thu Jan 22 16:26:46 2009 @@ -0,0 +1,346 @@ +/** + * Copyright 2008-2009 WorldWide Conferencing, LLC + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.esme.lib + +import org.specs._ +import org.specs.runner.JUnit3 +import org.specs.runner.ConsoleRunner +import net.liftweb.util._ +import org.specs.matcher._ +import Helpers._ +import MsgParser._ +import net.sourceforge.jwebunit.junit.WebTester +import org.mortbay.jetty.Server +//import org.mortbay.jetty.servlet.Context +import org.mortbay.jetty.servlet.ServletHolder +import org.mortbay.jetty.webapp.WebAppContext +import org.apache.esme._ +import model._ + +import net.sourceforge.jwebunit.junit.WebTester +import _root_.junit.framework.AssertionFailedError + +class MsgParserSpecsAsTest extends JUnit3(MsgParserSpecs) +object MsgParserSpecsRunner extends ConsoleRunner(MsgParserSpecs) + +object MsgParserSpecs extends Specification { + JettyTestServer.start() + + type PFT = MsgParser.ParseResult[_] + def parseMatch(name: String, matchr: PartialFunction[PFT, Any]) = new Matcher[PFT] { + def apply(v: => PFT) = (matchr.isDefinedAt(v), + name+" succeeded parsing", + name+" failed parsing") + } + + "Msg Parser Parse" should { + "parse top label" in { + val ret = MsgParser.toplabel("www") + + ret must + parseMatch("www", { + case MsgParser.Success("www", _) => + }) + } + + "parse a simple URL" in { + MsgParser.httpUrl("http://www.google.com") must + parseMatch("google", { + case MsgParser.Success("http://www.google.com", _) => + }) + } + + "parse a complex simple URL" in { + val Str = "http://www.google.com:8080/Foo/bar" + + val ret = MsgParser.httpUrl(Str) + + ret must + parseMatch("google + port", { + case MsgParser.Success(Str, _) => + }) + } + + "parse a complex URL with query params" in { + val Str = "https://www.sdn.sap.com/irj/sdn/weblogs?blog=/pub/wlg/10754" + + val ret = MsgParser.httpUrl(Str) + + ret must + parseMatch("sap thing", { + case MsgParser.Success(Str, _) => + }) + } + + "Fail for an empty string" in { + MsgParser.begin("") must + parseMatch("Empty", + {case MsgParser.Error(_, _) => + case MsgParser.Failure(_, _) => + }) + + } + + "Find only text" in { + MsgParser.begin("This is a message") must + parseMatch("only test", + {case MsgParser.Success(MsgText(_) :: Nil, _) => + + }) + + } + + "Find only text" in { + MsgParser.begin("This is http://$$$ a message") must + parseMatch("only test", + {case MsgParser.Success(MsgText(_) :: Nil, _) => + + }) + + } + + "Find only text" in { + MsgParser.begin("This is #,hello a message") must + parseMatch("only test", + {case MsgParser.Success(MsgText(_) :: Nil, _) => + + }) + + } + + "Find only text" in { + MsgParser.begin("This is @--Moose a message") must + parseMatch("only test", + {case MsgParser.Success(MsgText(_) :: Nil, _) => + + }) + + } + + "Find a hash tag" in { + MsgParser.begin("This is #hash a message") must + parseMatch("only test", + {case MsgParser.Success(MsgText(_) :: + HashTag(tag) :: + MsgText(_) :: Nil, _) + if tag.name.equalsIgnoreCase("hash") => + } + ) + + } + + "Find a @msg tag" in { + val ret = MsgParser.begin("This is @hash, a message") + + ret must + parseMatch("only test", + {case MsgParser.Success(MsgText(_) :: + AtName(_) :: + MsgText(_) :: Nil, _) => + } + ) + + } + + "Find a url tag" in { + MsgParser.begin("This is http://www.moo.com a message") must + parseMatch("only test", + {case MsgParser.Success(MsgText(_) :: + URL(_) :: + MsgText(_) :: Nil, _) => + } + ) + + } + + "Find a https url tag" in { + MsgParser.begin("This is https://www.moo.com a message") must + parseMatch("only test", + {case MsgParser.Success(MsgText(_) :: + URL(_) :: + MsgText(_) :: Nil, _) => + } + ) + + } + + "match 'any'" in { + val ret = MsgParser._testMessage("any") + + ret must + parseMatch("only test", + {case MsgParser.Success(AnyAction, _) => + } + ) + + } + + + "match '54%'" in { + val ret = MsgParser._testMessage(" 54% ") + + ret must + parseMatch("only test", + {case MsgParser.Success(PercentAction(54), _) => + } + ) + + } + + "match '#foo'" in { + val ret = MsgParser._testMessage(" #foo ") + + ret must + parseMatch("only test", + {case MsgParser.Success(HashAction(_, _), _) => + } + ) + + } + + /* + + "match '@hash'" in { + println("About to test @hash") + val ret = MsgParser._testMessage(" @hash ") + + println("hash is is "+ret) + + ret must + parseMatch("only test", + {case MsgParser.Success(AtUserAction(_), _) => + } + ) + + } + */ + + "match '@hasher'" in { + val ret = MsgParser._testMessage(" @hasher ") + + ret must + parseMatch(" @hasher ", + {case MsgParser.Failure(_ , _) => + } + ) + + } + + "match 'day = 4'" in { + val ret = MsgParser._testMessage(" day = 4 ") + + ret must + parseMatch("only test", + {case MsgParser.Success(DateTestAction(DayDateType, EqOpr, List(4)), _) => + } + ) + + } + + "match 'month = (1,2,4)'" in { + val ret = MsgParser._testMessage(" month = (1, 2, 4 ) ") + + ret must + parseMatch("only test", + {case MsgParser.Success(DateTestAction(MonthDateType, EqOpr, List(1, 2, 4)), _) => + } + ) + + } + + "match 'month = (1,2,4) | 74%'" in { + val ret = MsgParser._testMessage(" month = (1, 2, 4 )|74% ") + + ret must + parseMatch("only test", + {case MsgParser.Success(OrAction(DateTestAction(MonthDateType, EqOpr, List(1, 2, 4)), PercentAction(74)), _) => + } + ) + + } + + "match '( month = (1, 2, 4 )|74%) & #frog'" in { + val ret = MsgParser._testMessage("( month = (1, 2, 4 )|74%) & #frog ") + + ret must + parseMatch("only test", + {case MsgParser.Success(AndAction( + ParenAction(OrAction(DateTestAction(MonthDateType, EqOpr, List(1, 2, 4)), PercentAction(74))), + HashAction(_, _)), _) => + }) + + } + + } + +} + + +object JettyTestServer { + private val serverPort_ = System.getProperty("SERVLET_PORT", "8989").toInt + private var baseUrl_ = "http://127.0.0.1:" + serverPort_ + + System.setProperty("run.mode", "test") + + private val server_ : Server = { + val server = new Server(serverPort_) + val context = new WebAppContext() + context.setServer(server) + context.setContextPath("/") + context.setWar("src/main/webapp") + //val context = new Context(_server, "/", Context.SESSIONS) + //context.addFilter(new FilterHolder(new LiftFilter()), "/"); + server.addHandler(context) + server + } + + def urlFor(path: String) = baseUrl_ + path + + def start() = { + server_.start() + User.create.nickname("hash").save + } + + def stop() = { + server_.stop() + server_.join() + } + + def browse(startPath: String, f:(WebTester) => Unit) = { + val wc = new WebTester() + try { + wc.setScriptingEnabled(false) + wc.beginAt(JettyTestServer.urlFor(startPath)) + f(wc) + } catch { + case exc: AssertionFailedError => { + System.err.println("serveur response: ", wc.getServeurResponse()) + throw exc + } + } finally { + wc.closeBrowser() + } + } + +} + +
