IntegrationSpec.scala 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. import com.weEat.controllers.UserController
  2. import javax.inject.Inject
  3. import play.api.test.Helpers._
  4. import play.api.test.FakeRequest
  5. import play.api.libs.json.Json
  6. import org.openqa.selenium.By
  7. import org.scalatest.{Assertion,BeforeAndAfterAll,BeforeAndAfterEach}
  8. import org.scalatestplus.play._
  9. import org.scalatestplus.play.guice.GuiceOneServerPerSuite
  10. import com.weEat.shared.models.User
  11. import scala.concurrent.{Future,blocking}
  12. import scala.concurrent.duration._
  13. import scala.language.postfixOps
  14. import java.util.concurrent.TimeoutException
  15. import org.bson.types.ObjectId
  16. class IntegrationSpec @Inject()(
  17. userController: UserController
  18. ) extends PlaySpec
  19. with BeforeAndAfterAll
  20. with BeforeAndAfterEach
  21. with GuiceOneServerPerSuite
  22. with AllBrowsersPerTest {
  23. val users = Seq(
  24. (User(new ObjectId(), "test", "user", "tuser@sample.org"), "password"),
  25. (User(new ObjectId(), "another", "user", "usert@sample.org"), "password")
  26. )
  27. override def beforeAll() = {
  28. val Some(resp) = route(app, FakeRequest(PUT, "/v1/user/").withJsonBody(
  29. Json.parse(s"""|{
  30. | "fname": "${users(0)._1.fname}",
  31. | "lname": "${users(0)._1.lname}",
  32. | "email": "${users(0)._1.email}",
  33. | "password": "${users(0)._2}"
  34. |}""".stripMargin)
  35. ))
  36. status(resp) mustEqual OK
  37. }
  38. override def afterAll() = {
  39. implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global
  40. Future.sequence(Seq(
  41. userController.deleteUser(users(0)._1._id),
  42. )).map { (deletes) =>
  43. deletes must matchPattern {
  44. case Seq(_) =>
  45. }
  46. }
  47. // val Some(resp) = route(app, FakeRequest(DELETE, s"/v1/user/${users(0)._id}"))
  48. // status(resp) mustEqual OK
  49. // val Some(resp) = route(app, FakeRequest(DELETE, s"/v1/user/${users(1)._id}"))
  50. // status(resp) mustEqual OK
  51. }
  52. override lazy val browsers = Vector(
  53. FirefoxInfo(firefoxProfile),
  54. //ChromeInfo
  55. )
  56. val address = s"http://localhost:$port"
  57. /* Will repeatedly attempt to test until a result is returned.
  58. * A None value implies the test is not yet ready to run and will be attempted
  59. * again after the frequency has passed..
  60. *
  61. * A Some value means the test has completed with the contained assertion
  62. * result.
  63. */
  64. def poll(
  65. test: () => Option[Assertion],
  66. frequency: Duration = 100.millisecond
  67. ): Future[Assertion] = {
  68. test() match {
  69. case Some(result) => Future.successful(result)
  70. case None => {
  71. blocking {
  72. Thread.sleep(frequency.toMillis)
  73. }
  74. poll(test, frequency)
  75. }
  76. }
  77. }
  78. def waitForReady[T](
  79. timeout: Duration = 1 minute,
  80. period: Duration = 100 millisecond
  81. )(fn: => T): Future[T] =
  82. if (executeScript("return jQuery.active == 0 && selAsyncCount == 0;").asInstanceOf[Boolean])
  83. Future.successful(fn)
  84. else if (timeout < 0.second)
  85. Future.failed(new TimeoutException())
  86. else {
  87. blocking {
  88. Thread.sleep(period.toMillis)
  89. }
  90. waitForReady(timeout - period, period)(fn)
  91. }
  92. def sharedTests(browser: BrowserInfo) = {
  93. "The register menu" must {
  94. "display when register button is clicked " + browser.name in {
  95. go to address
  96. click on id("btn-signup")
  97. waitForReady() {
  98. click on id("view-register").webElement.findElement(By.xpath("./.."))
  99. //id("content").webElement.getText mustEqual ("")
  100. }
  101. }
  102. def testUserList() = {
  103. val Some(resp) = route(app, FakeRequest(GET, "/v1/user/"))
  104. status(resp) mustEqual OK
  105. contentAsJson(resp).as[Seq[String]] must matchPattern {
  106. case Seq(user1, user2) =>
  107. }
  108. }
  109. "accept a new user " + browser.name in {
  110. go to address
  111. click on id("btn-signup")
  112. waitForReady() {
  113. textField("email").value = users(1)._1.email
  114. name("password").webElement.sendKeys(users(1)._2)
  115. name("password2").webElement.sendKeys(users(1)._2)
  116. textField("fname").value = users(1)._1.fname
  117. textField("lname").value = users(1)._1.lname
  118. click on cssSelector("*[data-cb='success']")
  119. waitForReady() {
  120. find("#view-register") must be (None)
  121. id("btn-logout").webElement must be ("displayed")
  122. // id("content").webElement.getText
  123. // .mustEqual(s"Hello, ${users(1)._1.fname} ${users(1)._1.lname}!")
  124. // testUserList()
  125. }
  126. }
  127. }
  128. "reject a used email " + browser.name in {
  129. go to address
  130. click on id("btn-signup")
  131. waitForReady() {
  132. textField("email").value = users(0)._1.email
  133. name("password").webElement.sendKeys("_"+users(0)._2)
  134. name("password2").webElement.sendKeys("_"+users(0)._2)
  135. textField("fname").value = "_"+users(0)._1.fname
  136. textField("lname").value = "_"+users(0)._1.lname
  137. click on cssSelector("*[data-cb='success']")
  138. waitForReady() {
  139. cssSelector(".alert-danger").webElement.getText
  140. .mustEqual("Error: This email address is already registered.")
  141. id("btn-logout").webElement mustNot be ("displayed")
  142. //id("content").webElement.getText mustEqual("")
  143. testUserList()
  144. }
  145. }
  146. }
  147. "reject an invalid email " + browser.name in {
  148. go to address
  149. click on id("btn-signup")
  150. waitForReady() {
  151. textField("email").value = "hello World!"
  152. name("password").webElement.sendKeys("_"+users(0)._2)
  153. name("password2").webElement.sendKeys("_"+users(0)._2)
  154. textField("fname").value = "_"+users(0)._1.fname
  155. textField("lname").value = "_"+users(0)._1.lname
  156. click on cssSelector("*[data-cb='success']")
  157. waitForReady() {
  158. cssSelector(".alert-danger").webElement.getText
  159. .mustEqual("Error: Invalid email.")
  160. id("btn-logout").webElement mustNot be ("displayed")
  161. //id("content").webElement.getText mustEqual("")
  162. testUserList()
  163. }
  164. }
  165. }
  166. "reject a password below 8 characters " + browser.name in {
  167. go to address
  168. click on id("btn-signup")
  169. waitForReady() {
  170. textField("email").value = "_"+users(0)._1.email
  171. name("password").webElement.sendKeys("1234567")
  172. name("password2").webElement.sendKeys("1234567")
  173. textField("fname").value = "_"+users(0)._1.fname
  174. textField("lname").value = "_"+users(0)._1.lname
  175. click on cssSelector("*[data-cb='success']")
  176. waitForReady() {
  177. cssSelector(".alert-danger").webElement.getText
  178. .mustEqual("Error: Password too short (Minimum 8 characters).")
  179. id("btn-logout").webElement mustNot be ("displayed")
  180. //id("content").webElement.getText mustEqual("")
  181. testUserList()
  182. }
  183. }
  184. }
  185. "reject a non-matching passwords " + browser.name in {
  186. go to address
  187. click on id("btn-signup")
  188. waitForReady() {
  189. textField("email").value = "_"+users(0)._1.email
  190. name("password").webElement.sendKeys(users(0)._2)
  191. name("password2").webElement.sendKeys("_"+users(0)._2)
  192. textField("fname").value = "_"+users(0)._1.fname
  193. textField("lname").value = "_"+users(0)._1.lname
  194. click on cssSelector("*[data-cb='success']")
  195. waitForReady() {
  196. cssSelector(".alert-danger").webElement.getText
  197. .mustEqual("Error: Passwords do not match.")
  198. id("btn-logout").webElement mustNot be ("displayed")
  199. //id("content").webElement.getText mustEqual("")
  200. testUserList()
  201. }
  202. }
  203. }
  204. }
  205. "The login menu" must {
  206. "display when login button is clicked " + browser.name in {
  207. go to address
  208. click on id("btn-login")
  209. waitForReady() {
  210. click on id("view-login").webElement.findElement(By.xpath("./.."))
  211. id("btn-logout").webElement mustNot be ("displayed")
  212. //id("content").webElement.getText mustEqual("")
  213. }
  214. }
  215. "accept user created from API " + browser.name in {
  216. go to address
  217. click on id("btn-login")
  218. waitForReady() {
  219. textField("email").value = users(0)._1.email
  220. name("password").webElement.sendKeys(users(0)._2)
  221. click on cssSelector("*[data-cb='success']")
  222. waitForReady() {
  223. find("#view-login") must be (None)
  224. id("btn-logout").webElement must be ("displayed")
  225. // id("content").webElement.getText
  226. // .mustEqual(s"Hello, ${users(0)._1.fname} ${users(0)._1.lname}!")
  227. }
  228. }
  229. }
  230. "accept user created from UI " + browser.name in {
  231. go to address
  232. click on id("btn-login")
  233. waitForReady() {
  234. textField("email").value = users(1)._1.email
  235. name("password").webElement.sendKeys(users(1)._2)
  236. click on cssSelector("*[data-cb='success']")
  237. waitForReady() {
  238. find("#view-login") must be (None)
  239. id("btn-logout").webElement must be ("displayed")
  240. // id("content").webElement.getText
  241. // .mustEqual(s"Hello, ${users(1)._1.fname} ${users(1)._1.lname}!")
  242. }
  243. }
  244. }
  245. "reject an incorrect email " + browser.name in {
  246. go to address
  247. click on id("btn-login")
  248. waitForReady() {
  249. textField("email").value = "_"+users(1)._1.email
  250. name("password").webElement.sendKeys(users(0)._2)
  251. click on cssSelector("*[data-cb='success']")
  252. waitForReady() {
  253. cssSelector(".alert-danger").webElement.getText
  254. .mustEqual("Error: Invalid client or client is not authorized")
  255. id("btn-logout").webElement mustNot be ("displayed")
  256. //id("content").webElement.getText mustEqual("")
  257. }
  258. }
  259. }
  260. "reject an incorrect password " + browser.name in {
  261. go to address
  262. click on id("btn-login")
  263. waitForReady() {
  264. textField("email").value = users(1)._1.email
  265. name("password").webElement.sendKeys("_"+users(0)._2)
  266. click on cssSelector("*[data-cb='success']")
  267. waitForReady() {
  268. cssSelector(".alert-danger").webElement.getText
  269. .mustEqual("Error: Invalid client or client is not authorized")
  270. id("btn-logout").webElement mustNot be ("displayed")
  271. //id("content").webElement.getText mustEqual("")
  272. }
  273. }
  274. }
  275. "reject an incorrect email and password " + browser.name in {
  276. go to address
  277. click on id("btn-login")
  278. waitForReady() {
  279. textField("email").value = "_"+users(1)._1.email
  280. name("password").webElement.sendKeys("_"+users(0)._2)
  281. click on cssSelector("*[data-cb='success']")
  282. waitForReady() {
  283. cssSelector(".alert-danger").webElement.getText
  284. .mustEqual("Error: Invalid client or client is not authorized")
  285. id("btn-logout").webElement mustNot be ("displayed")
  286. //id("content").webElement.getText mustEqual("")
  287. }
  288. }
  289. }
  290. "maintain login info across refresh " + browser.name in {
  291. go to address
  292. click on id("btn-login")
  293. waitForReady() {
  294. textField("email").value = users(1)._1.email
  295. name("password").webElement.sendKeys(users(1)._2)
  296. click on cssSelector("*[data-cb='success']")
  297. waitForReady() {
  298. go to address
  299. waitForReady() {
  300. find("#view-login") must be (None)
  301. id("btn-logout").webElement must be ("displayed")
  302. // id("content").webElement.getText
  303. // .mustEqual(s"Hello, ${users(1)._1.fname} ${users(1)._1.lname}!")
  304. id("btn-logout").webElement must be ("displayed")
  305. }
  306. }
  307. }
  308. }
  309. }
  310. "The logout button" must {
  311. "not display when not logged in " + browser.name in {
  312. go to address
  313. waitForReady() {
  314. id("btn-logout").webElement mustNot be ("displayed")
  315. //id("content").webElement.getText mustEqual("")
  316. }
  317. }
  318. "display when logged in" + browser.name in {
  319. go to address
  320. click on id("btn-login")
  321. waitForReady() {
  322. textField("email").value = users(0)._1.email
  323. name("password").webElement.sendKeys(users(0)._2)
  324. click on cssSelector("*[data-cb='success']")
  325. waitForReady() {
  326. id("btn-logout").webElement must be ("displayed")
  327. }
  328. }
  329. }
  330. "remove user information when clicked " + browser.name in {
  331. go to address
  332. click on id("btn-login")
  333. waitForReady() {
  334. textField("email").value = users(0)._1.email
  335. name("password").webElement.sendKeys(users(0)._2)
  336. click on cssSelector("*[data-cb='success']")
  337. waitForReady() {
  338. click on id("btn-logout")
  339. waitForReady() {
  340. id("btn-logout").webElement mustNot be ("displayed")
  341. //id("content").webElement.getText mustEqual("")
  342. }
  343. }
  344. }
  345. }
  346. "remove stored user information when clicked " + browser.name in {
  347. go to address
  348. click on id("btn-login")
  349. waitForReady() {
  350. textField("email").value = users(0)._1.email
  351. name("password").webElement.sendKeys(users(0)._2)
  352. click on cssSelector("*[data-cb='success']")
  353. waitForReady() {
  354. click on id("btn-logout")
  355. waitForReady() {
  356. go to address
  357. id("btn-logout").webElement mustNot be ("displayed")
  358. //id("content").webElement.getText mustEqual("")
  359. }
  360. }
  361. }
  362. }
  363. }
  364. }
  365. }