mirror of
				https://github.com/arcan1s/ffxivbis.git
				synced 2025-10-30 13:13:41 +00:00 
			
		
		
		
	moar tests
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -85,3 +85,4 @@ project/plugins/project/ | |||||||
| .ensime | .ensime | ||||||
|  |  | ||||||
| *.db | *.db | ||||||
|  | *.sc | ||||||
|  | |||||||
| @ -20,7 +20,7 @@ class BiSHelper(storage: ActorRef, ariyala: ActorRef) extends AriyalaHelper(ariy | |||||||
|  |  | ||||||
|   def addPieceBiS(playerId: PlayerId, piece: Piece) |   def addPieceBiS(playerId: PlayerId, piece: Piece) | ||||||
|                  (implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] = |                  (implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] = | ||||||
|     (storage ? DatabaseBiSHandler.AddPieceToBis(playerId, piece)).mapTo[Int] |     (storage ? DatabaseBiSHandler.AddPieceToBis(playerId, piece.withJob(playerId.job))).mapTo[Int] | ||||||
|  |  | ||||||
|   def bis(partyId: String, playerId: Option[PlayerId]) |   def bis(partyId: String, playerId: Option[PlayerId]) | ||||||
|          (implicit executionContext: ExecutionContext, timeout: Timeout): Future[Seq[Player]] = |          (implicit executionContext: ExecutionContext, timeout: Timeout): Future[Seq[Player]] = | ||||||
| @ -28,7 +28,9 @@ class BiSHelper(storage: ActorRef, ariyala: ActorRef) extends AriyalaHelper(ariy | |||||||
|  |  | ||||||
|   def putBiS(playerId: PlayerId, link: String) |   def putBiS(playerId: PlayerId, link: String) | ||||||
|             (implicit executionContext: ExecutionContext, timeout: Timeout): Future[Unit] = |             (implicit executionContext: ExecutionContext, timeout: Timeout): Future[Unit] = | ||||||
|     downloadBiS(link, playerId.job).map(_.pieces.map(addPieceBiS(playerId, _))) |     downloadBiS(link, playerId.job).flatMap { bis => | ||||||
|  |       Future.traverse(bis.pieces)(addPieceBiS(playerId, _)) | ||||||
|  |     }.map(_ => ()) | ||||||
|  |  | ||||||
|   def removePieceBiS(playerId: PlayerId, piece: Piece) |   def removePieceBiS(playerId: PlayerId, piece: Piece) | ||||||
|                     (implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] = |                     (implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] = | ||||||
|  | |||||||
| @ -88,7 +88,7 @@ class UserEndpoint(override val storage: ActorRef)(implicit timeout: Timeout) | |||||||
|             entity(as[UserResponse]) { user => |             entity(as[UserResponse]) { user => | ||||||
|               val withPartyId = user.toUser.copy(partyId = partyId) |               val withPartyId = user.toUser.copy(partyId = partyId) | ||||||
|               complete { |               complete { | ||||||
|                 addUser(withPartyId, isHashedPassword = false).map(_ => (StatusCodes.Created, HttpEntity.Empty)) |                 addUser(withPartyId, isHashedPassword = false).map(_ => (StatusCodes.Accepted, HttpEntity.Empty)) | ||||||
|               } |               } | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol { | |||||||
|     new RootJsonFormat[E#Value] { |     new RootJsonFormat[E#Value] { | ||||||
|       override def write(obj: E#Value): JsValue = obj.toString.toJson |       override def write(obj: E#Value): JsValue = obj.toString.toJson | ||||||
|       override def read(json: JsValue): E#Value = json match { |       override def read(json: JsValue): E#Value = json match { | ||||||
|  |         case JsNumber(value) => enum(value.toInt) | ||||||
|         case JsString(name) => enum.withName(name) |         case JsString(name) => enum.withName(name) | ||||||
|         case other => deserializationError(s"String or number expected, got $other") |         case other => deserializationError(s"String or number expected, got $other") | ||||||
|       } |       } | ||||||
| @ -27,11 +28,11 @@ trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol { | |||||||
|   implicit val permissionFormat: RootJsonFormat[Permission.Value] = enumFormat(Permission) |   implicit val permissionFormat: RootJsonFormat[Permission.Value] = enumFormat(Permission) | ||||||
|  |  | ||||||
|   implicit val pieceFormat: RootJsonFormat[PieceResponse] = jsonFormat3(PieceResponse.apply) |   implicit val pieceFormat: RootJsonFormat[PieceResponse] = jsonFormat3(PieceResponse.apply) | ||||||
|   implicit val pieceActionFormat: RootJsonFormat[PieceActionResponse] = jsonFormat3(PieceActionResponse.apply) |  | ||||||
|   implicit val playerFormat: RootJsonFormat[PlayerResponse] = jsonFormat7(PlayerResponse.apply) |   implicit val playerFormat: RootJsonFormat[PlayerResponse] = jsonFormat7(PlayerResponse.apply) | ||||||
|   implicit val playerActionFormat: RootJsonFormat[PlayerActionResponse] = jsonFormat2(PlayerActionResponse.apply) |   implicit val playerActionFormat: RootJsonFormat[PlayerActionResponse] = jsonFormat2(PlayerActionResponse.apply) | ||||||
|   implicit val playerBiSLinkFormat: RootJsonFormat[PlayerBiSLinkResponse] = jsonFormat2(PlayerBiSLinkResponse.apply) |  | ||||||
|   implicit val playerIdFormat: RootJsonFormat[PlayerIdResponse] = jsonFormat3(PlayerIdResponse.apply) |   implicit val playerIdFormat: RootJsonFormat[PlayerIdResponse] = jsonFormat3(PlayerIdResponse.apply) | ||||||
|  |   implicit val pieceActionFormat: RootJsonFormat[PieceActionResponse] = jsonFormat3(PieceActionResponse.apply) | ||||||
|  |   implicit val playerBiSLinkFormat: RootJsonFormat[PlayerBiSLinkResponse] = jsonFormat2(PlayerBiSLinkResponse.apply) | ||||||
|   implicit val playerIdWithCountersFormat: RootJsonFormat[PlayerIdWithCountersResponse] = |   implicit val playerIdWithCountersFormat: RootJsonFormat[PlayerIdWithCountersResponse] = | ||||||
|     jsonFormat9(PlayerIdWithCountersResponse.apply) |     jsonFormat9(PlayerIdWithCountersResponse.apply) | ||||||
|   implicit val userFormat: RootJsonFormat[UserResponse] = jsonFormat4(UserResponse.apply) |   implicit val userFormat: RootJsonFormat[UserResponse] = jsonFormat4(UserResponse.apply) | ||||||
|  | |||||||
| @ -18,3 +18,8 @@ case class PlayerIdResponse( | |||||||
|   def withPartyId(partyId: String): PlayerId = |   def withPartyId(partyId: String): PlayerId = | ||||||
|     PlayerId(partyId, Job.withName(job), nick) |     PlayerId(partyId, Job.withName(job), nick) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | object PlayerIdResponse { | ||||||
|  |   def fromPlayerId(playerId: PlayerId): PlayerIdResponse = | ||||||
|  |     PlayerIdResponse(Some(playerId.partyId), playerId.job.toString, playerId.nick) | ||||||
|  | } | ||||||
|  | |||||||
| @ -8,11 +8,13 @@ | |||||||
|  */ |  */ | ||||||
| package me.arcanis.ffxivbis.models | package me.arcanis.ffxivbis.models | ||||||
|  |  | ||||||
| trait Piece { | sealed trait Piece { | ||||||
|   def isTome: Boolean |   def isTome: Boolean | ||||||
|   def job: Job.Job |   def job: Job.Job | ||||||
|   def piece: String |   def piece: String | ||||||
|  |  | ||||||
|  |   def withJob(other: Job.Job): Piece | ||||||
|  |  | ||||||
|   def isTomeToString: String = if (isTome) "yes" else "no" |   def isTomeToString: String = if (isTome) "yes" else "no" | ||||||
|   def upgrade: Option[PieceUpgrade] = this match { |   def upgrade: Option[PieceUpgrade] = this match { | ||||||
|     case _ if !isTome => None |     case _ if !isTome => None | ||||||
| @ -20,7 +22,6 @@ trait Piece { | |||||||
|     case _: PieceAccessory => Some(AccessoryUpgrade) |     case _: PieceAccessory => Some(AccessoryUpgrade) | ||||||
|     case _: PieceBody => Some(BodyUpgrade) |     case _: PieceBody => Some(BodyUpgrade) | ||||||
|     case _: PieceWeapon => Some(WeaponUpgrade) |     case _: PieceWeapon => Some(WeaponUpgrade) | ||||||
|     case _ => None |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -29,43 +30,55 @@ trait PieceBody extends Piece | |||||||
| trait PieceUpgrade extends Piece { | trait PieceUpgrade extends Piece { | ||||||
|   val isTome: Boolean = true |   val isTome: Boolean = true | ||||||
|   val job: Job.Job = Job.AnyJob |   val job: Job.Job = Job.AnyJob | ||||||
|  |   def withJob(other: Job.Job): Piece = this | ||||||
| } | } | ||||||
| trait PieceWeapon extends Piece | trait PieceWeapon extends Piece | ||||||
|  |  | ||||||
| case class Weapon(override val isTome: Boolean, override val job: Job.Job) extends PieceWeapon { | case class Weapon(override val isTome: Boolean, override val job: Job.Job) extends PieceWeapon { | ||||||
|   val piece: String = "weapon" |   val piece: String = "weapon" | ||||||
|  |   def withJob(other: Job.Job): Piece = copy(job = other) | ||||||
| } | } | ||||||
|  |  | ||||||
| case class Head(override val isTome: Boolean, override val job: Job.Job) extends PieceBody { | case class Head(override val isTome: Boolean, override val job: Job.Job) extends PieceBody { | ||||||
|   val piece: String = "head" |   val piece: String = "head" | ||||||
|  |   def withJob(other: Job.Job): Piece = copy(job = other) | ||||||
| } | } | ||||||
| case class Body(override val isTome: Boolean, override val job: Job.Job) extends PieceBody { | case class Body(override val isTome: Boolean, override val job: Job.Job) extends PieceBody { | ||||||
|   val piece: String = "body" |   val piece: String = "body" | ||||||
|  |   def withJob(other: Job.Job): Piece = copy(job = other) | ||||||
| } | } | ||||||
| case class Hands(override val isTome: Boolean, override val job: Job.Job) extends PieceBody { | case class Hands(override val isTome: Boolean, override val job: Job.Job) extends PieceBody { | ||||||
|   val piece: String = "hands" |   val piece: String = "hands" | ||||||
|  |   def withJob(other: Job.Job): Piece = copy(job = other) | ||||||
| } | } | ||||||
| case class Waist(override val isTome: Boolean, override val job: Job.Job) extends PieceBody { | case class Waist(override val isTome: Boolean, override val job: Job.Job) extends PieceBody { | ||||||
|   val piece: String = "waist" |   val piece: String = "waist" | ||||||
|  |   def withJob(other: Job.Job): Piece = copy(job = other) | ||||||
| } | } | ||||||
| case class Legs(override val isTome: Boolean, override val job: Job.Job) extends PieceBody { | case class Legs(override val isTome: Boolean, override val job: Job.Job) extends PieceBody { | ||||||
|   val piece: String = "legs" |   val piece: String = "legs" | ||||||
|  |   def withJob(other: Job.Job): Piece = copy(job = other) | ||||||
| } | } | ||||||
| case class Feet(override val isTome: Boolean, override val job: Job.Job) extends PieceBody { | case class Feet(override val isTome: Boolean, override val job: Job.Job) extends PieceBody { | ||||||
|   val piece: String = "feet" |   val piece: String = "feet" | ||||||
|  |   def withJob(other: Job.Job): Piece = copy(job = other) | ||||||
| } | } | ||||||
|  |  | ||||||
| case class Ears(override val isTome: Boolean, override val job: Job.Job) extends PieceAccessory { | case class Ears(override val isTome: Boolean, override val job: Job.Job) extends PieceAccessory { | ||||||
|   val piece: String = "ears" |   val piece: String = "ears" | ||||||
|  |   def withJob(other: Job.Job): Piece = copy(job = other) | ||||||
| } | } | ||||||
| case class Neck(override val isTome: Boolean, override val job: Job.Job) extends PieceAccessory { | case class Neck(override val isTome: Boolean, override val job: Job.Job) extends PieceAccessory { | ||||||
|   val piece: String = "neck" |   val piece: String = "neck" | ||||||
|  |   def withJob(other: Job.Job): Piece = copy(job = other) | ||||||
| } | } | ||||||
| case class Wrist(override val isTome: Boolean, override val job: Job.Job) extends PieceAccessory { | case class Wrist(override val isTome: Boolean, override val job: Job.Job) extends PieceAccessory { | ||||||
|   val piece: String = "wrist" |   val piece: String = "wrist" | ||||||
|  |   def withJob(other: Job.Job): Piece = copy(job = other) | ||||||
| } | } | ||||||
| case class Ring(override val isTome: Boolean, override val job: Job.Job, override val piece: String = "ring") | case class Ring(override val isTome: Boolean, override val job: Job.Job, override val piece: String = "ring") | ||||||
|   extends PieceAccessory { |   extends PieceAccessory { | ||||||
|  |   def withJob(other: Job.Job): Piece = copy(job = other) | ||||||
|   override def equals(obj: Any): Boolean = obj match { |   override def equals(obj: Any): Boolean = obj match { | ||||||
|     case Ring(thatIsTome, thatJob, _) => (thatIsTome == isTome) && (thatJob == job) |     case Ring(thatIsTome, thatJob, _) => (thatIsTome == isTome) && (thatJob == job) | ||||||
|     case _ => false |     case _ => false | ||||||
|  | |||||||
| @ -33,8 +33,8 @@ class Ariyala extends Actor with StrictLogging { | |||||||
|   private val xivapiKey = Try(settings.getString("me.arcanis.ffxivbis.ariyala.xivapi-key")).toOption |   private val xivapiKey = Try(settings.getString("me.arcanis.ffxivbis.ariyala.xivapi-key")).toOption | ||||||
|  |  | ||||||
|   private val http = Http()(context.system) |   private val http = Http()(context.system) | ||||||
|   private implicit val materializer: ActorMaterializer = ActorMaterializer() |   implicit private val materializer: ActorMaterializer = ActorMaterializer() | ||||||
|   private implicit val executionContext: ExecutionContext = context.dispatcher |   implicit private val executionContext: ExecutionContext = context.dispatcher | ||||||
|  |  | ||||||
|   override def receive: Receive = { |   override def receive: Receive = { | ||||||
|     case GetBiS(link, job) => |     case GetBiS(link, job) => | ||||||
|  | |||||||
| @ -0,0 +1,108 @@ | |||||||
|  | package me.arcanis.ffxivbis.http.api.v1 | ||||||
|  |  | ||||||
|  | import akka.actor.ActorRef | ||||||
|  | import akka.http.scaladsl.model.{StatusCodes, Uri} | ||||||
|  | import akka.http.scaladsl.model.headers.{Authorization, BasicHttpCredentials} | ||||||
|  | import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest} | ||||||
|  | import akka.http.scaladsl.server._ | ||||||
|  | import akka.pattern.ask | ||||||
|  | import akka.testkit.TestKit | ||||||
|  | import com.typesafe.config.Config | ||||||
|  | import me.arcanis.ffxivbis.{Fixtures, Settings} | ||||||
|  | import me.arcanis.ffxivbis.http.api.v1.json._ | ||||||
|  | import me.arcanis.ffxivbis.models.BiS | ||||||
|  | import me.arcanis.ffxivbis.service.{Ariyala, impl} | ||||||
|  | import me.arcanis.ffxivbis.storage.Migration | ||||||
|  | import org.scalatest.{Matchers, WordSpec} | ||||||
|  |  | ||||||
|  | import scala.concurrent.Await | ||||||
|  | import scala.concurrent.duration._ | ||||||
|  | import scala.language.postfixOps | ||||||
|  |  | ||||||
|  | class BiSEndpointTest extends WordSpec | ||||||
|  |   with Matchers with ScalatestRouteTest with JsonSupport { | ||||||
|  |  | ||||||
|  |   private val auth: Authorization = | ||||||
|  |     Authorization(BasicHttpCredentials(Fixtures.userAdmin.username, Fixtures.userPassword)) | ||||||
|  |   private val endpoint: Uri = Uri(s"/party/${Fixtures.partyId}/bis") | ||||||
|  |   private val playerId = PlayerIdResponse.fromPlayerId(Fixtures.playerEmpty.playerId) | ||||||
|  |   private val timeout: FiniteDuration = 60 seconds | ||||||
|  |   implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(timeout) | ||||||
|  |  | ||||||
|  |   private val storage: ActorRef = system.actorOf(impl.DatabaseImpl.props) | ||||||
|  |   private val ariyala: ActorRef = system.actorOf(Ariyala.props) | ||||||
|  |   private val route: Route = new BiSEndpoint(storage, ariyala)(timeout).route | ||||||
|  |  | ||||||
|  |   override def testConfig: Config = Settings.withRandomDatabase | ||||||
|  |  | ||||||
|  |   override def beforeAll: Unit = { | ||||||
|  |     Await.result(Migration(system.settings.config), timeout) | ||||||
|  |     Await.result((storage ? impl.DatabaseUserHandler.AddUser(Fixtures.userAdmin, isHashedPassword = true))(timeout).mapTo[Int], timeout) | ||||||
|  |     Await.result((storage ? impl.DatabasePartyHandler.AddPlayer(Fixtures.playerEmpty))(timeout).mapTo[Int], timeout) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   override def afterAll: Unit = { | ||||||
|  |     TestKit.shutdownActorSystem(system) | ||||||
|  |     Settings.clearDatabase(system.settings.config) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   "api v1 bis endpoint" must { | ||||||
|  |  | ||||||
|  |     "create best in slot set from ariyala" in { | ||||||
|  |       val entity = PlayerBiSLinkResponse(Fixtures.link, playerId) | ||||||
|  |  | ||||||
|  |       Put(endpoint, entity).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.Created | ||||||
|  |         responseAs[String] shouldEqual "" | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     "return best in slot set" in { | ||||||
|  |       val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job))) | ||||||
|  |       val response = Seq(PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(Fixtures.bis)))) | ||||||
|  |  | ||||||
|  |       Get(uri).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.OK | ||||||
|  |         responseAs[Seq[PlayerResponse]] shouldEqual response | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     "remove item from best in slot set" in { | ||||||
|  |       val piece = PieceResponse.fromPiece(Fixtures.lootBody) | ||||||
|  |       val entity = PieceActionResponse(ApiAction.remove, piece, playerId) | ||||||
|  |  | ||||||
|  |       Post(endpoint, entity).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.Accepted | ||||||
|  |         responseAs[String] shouldEqual "" | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job))) | ||||||
|  |       val bis = BiS(Fixtures.bis.pieces.filterNot(_ == Fixtures.lootBody)) | ||||||
|  |       val response = Seq(PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(bis)))) | ||||||
|  |  | ||||||
|  |       Get(uri).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.OK | ||||||
|  |         responseAs[Seq[PlayerResponse]] shouldEqual response | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     "add item to best in slot set" in { | ||||||
|  |       val piece = PieceResponse.fromPiece(Fixtures.lootBody) | ||||||
|  |       val entity = PieceActionResponse(ApiAction.add, piece, playerId) | ||||||
|  |  | ||||||
|  |       Post(endpoint, entity).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.Accepted | ||||||
|  |         responseAs[String] shouldEqual "" | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job))) | ||||||
|  |       val response = Seq(PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(Fixtures.bis)))) | ||||||
|  |  | ||||||
|  |       Get(uri).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.OK | ||||||
|  |         responseAs[Seq[PlayerResponse]] shouldEqual response | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,88 @@ | |||||||
|  | package me.arcanis.ffxivbis.http.api.v1 | ||||||
|  |  | ||||||
|  | import akka.actor.ActorRef | ||||||
|  | import akka.http.scaladsl.model.{StatusCodes, Uri} | ||||||
|  | import akka.http.scaladsl.model.headers.{Authorization, BasicHttpCredentials} | ||||||
|  | import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest} | ||||||
|  | import akka.http.scaladsl.server._ | ||||||
|  | import akka.pattern.ask | ||||||
|  | import akka.testkit.TestKit | ||||||
|  | import com.typesafe.config.Config | ||||||
|  | import me.arcanis.ffxivbis.{Fixtures, Settings} | ||||||
|  | import me.arcanis.ffxivbis.http.api.v1.json._ | ||||||
|  | import me.arcanis.ffxivbis.service.impl | ||||||
|  | import me.arcanis.ffxivbis.storage.Migration | ||||||
|  | import org.scalatest.{Matchers, WordSpec} | ||||||
|  |  | ||||||
|  | import scala.concurrent.Await | ||||||
|  | import scala.concurrent.duration._ | ||||||
|  | import scala.language.postfixOps | ||||||
|  |  | ||||||
|  | class LootEndpointTest extends WordSpec | ||||||
|  |   with Matchers with ScalatestRouteTest with JsonSupport { | ||||||
|  |  | ||||||
|  |   private val auth: Authorization = | ||||||
|  |     Authorization(BasicHttpCredentials(Fixtures.userAdmin.username, Fixtures.userPassword)) | ||||||
|  |   private val endpoint: Uri = Uri(s"/party/${Fixtures.partyId}/loot") | ||||||
|  |   private val playerId = PlayerIdResponse.fromPlayerId(Fixtures.playerEmpty.playerId) | ||||||
|  |   private val timeout: FiniteDuration = 60 seconds | ||||||
|  |   implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(timeout) | ||||||
|  |  | ||||||
|  |   private val storage: ActorRef = system.actorOf(impl.DatabaseImpl.props) | ||||||
|  |   private val route: Route = new LootEndpoint(storage)(timeout).route | ||||||
|  |  | ||||||
|  |   override def testConfig: Config = Settings.withRandomDatabase | ||||||
|  |  | ||||||
|  |   override def beforeAll: Unit = { | ||||||
|  |     Await.result(Migration(system.settings.config), timeout) | ||||||
|  |     Await.result((storage ? impl.DatabaseUserHandler.AddUser(Fixtures.userAdmin, isHashedPassword = true))(timeout).mapTo[Int], timeout) | ||||||
|  |     Await.result((storage ? impl.DatabasePartyHandler.AddPlayer(Fixtures.playerEmpty))(timeout).mapTo[Int], timeout) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   override def afterAll: Unit = { | ||||||
|  |     TestKit.shutdownActorSystem(system) | ||||||
|  |     Settings.clearDatabase(system.settings.config) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   "api v1 loot endpoint" must { | ||||||
|  |  | ||||||
|  |     "add item to loot" in { | ||||||
|  |       val piece = PieceResponse.fromPiece(Fixtures.lootBody) | ||||||
|  |       val entity = PieceActionResponse(ApiAction.add, piece, playerId) | ||||||
|  |  | ||||||
|  |       Post(endpoint, entity).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.Accepted | ||||||
|  |         responseAs[String] shouldEqual "" | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     "return looted items" in { | ||||||
|  |       val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job))) | ||||||
|  |       val response = Seq(PlayerResponse.fromPlayer(Fixtures.playerEmpty.withLoot(Fixtures.lootBody))) | ||||||
|  |  | ||||||
|  |       Get(uri).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.OK | ||||||
|  |         responseAs[Seq[PlayerResponse]] shouldEqual response | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     "remove item from loot" in { | ||||||
|  |       val piece = PieceResponse.fromPiece(Fixtures.lootBody) | ||||||
|  |       val entity = PieceActionResponse(ApiAction.remove, piece, playerId) | ||||||
|  |  | ||||||
|  |       Post(endpoint, entity).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.Accepted | ||||||
|  |         responseAs[String] shouldEqual "" | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job))) | ||||||
|  |       val response = Seq(PlayerResponse.fromPlayer(Fixtures.playerEmpty)) | ||||||
|  |  | ||||||
|  |       Get(uri).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.OK | ||||||
|  |         responseAs[Seq[PlayerResponse]] shouldEqual response | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,61 @@ | |||||||
|  | package me.arcanis.ffxivbis.http.api.v1 | ||||||
|  |  | ||||||
|  | import akka.actor.ActorRef | ||||||
|  | import akka.http.scaladsl.model.{StatusCodes, Uri} | ||||||
|  | import akka.http.scaladsl.model.headers.{Authorization, BasicHttpCredentials} | ||||||
|  | import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest} | ||||||
|  | import akka.http.scaladsl.server._ | ||||||
|  | import akka.pattern.ask | ||||||
|  | import akka.testkit.TestKit | ||||||
|  | import com.typesafe.config.Config | ||||||
|  | import me.arcanis.ffxivbis.{Fixtures, Settings} | ||||||
|  | import me.arcanis.ffxivbis.http.api.v1.json._ | ||||||
|  | import me.arcanis.ffxivbis.service.{Ariyala, impl} | ||||||
|  | import me.arcanis.ffxivbis.storage.Migration | ||||||
|  | import org.scalatest.{Matchers, WordSpec} | ||||||
|  |  | ||||||
|  | import scala.concurrent.Await | ||||||
|  | import scala.concurrent.duration._ | ||||||
|  | import scala.language.postfixOps | ||||||
|  |  | ||||||
|  | class PartyEndpointTest extends WordSpec | ||||||
|  |   with Matchers with ScalatestRouteTest with JsonSupport { | ||||||
|  |  | ||||||
|  |   private val auth: Authorization = | ||||||
|  |     Authorization(BasicHttpCredentials(Fixtures.userAdmin.username, Fixtures.userPassword)) | ||||||
|  |   private val endpoint: Uri = Uri(s"/party/${Fixtures.partyId}") | ||||||
|  |   private val playerId = PlayerIdResponse.fromPlayerId(Fixtures.playerEmpty.playerId) | ||||||
|  |   private val timeout: FiniteDuration = 60 seconds | ||||||
|  |   implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(timeout) | ||||||
|  |  | ||||||
|  |   private val storage: ActorRef = system.actorOf(impl.DatabaseImpl.props) | ||||||
|  |   private val ariyala: ActorRef = system.actorOf(Ariyala.props) | ||||||
|  |   private val route: Route = new PlayerEndpoint(storage, ariyala)(timeout).route | ||||||
|  |  | ||||||
|  |   override def testConfig: Config = Settings.withRandomDatabase | ||||||
|  |  | ||||||
|  |   override def beforeAll: Unit = { | ||||||
|  |     Await.result(Migration(system.settings.config), timeout) | ||||||
|  |     Await.result((storage ? impl.DatabaseUserHandler.AddUser(Fixtures.userAdmin, isHashedPassword = true))(timeout).mapTo[Int], timeout) | ||||||
|  |     Await.result((storage ? impl.DatabasePartyHandler.AddPlayer(Fixtures.playerEmpty))(timeout).mapTo[Int], timeout) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   override def afterAll: Unit = { | ||||||
|  |     TestKit.shutdownActorSystem(system) | ||||||
|  |     Settings.clearDatabase(system.settings.config) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   "api v1 party endpoint" must { | ||||||
|  |  | ||||||
|  |     "get users" in { | ||||||
|  |       val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job))) | ||||||
|  |       val response = Seq(PlayerResponse.fromPlayer(Fixtures.playerEmpty)) | ||||||
|  |  | ||||||
|  |       Get(endpoint).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.OK | ||||||
|  |         responseAs[Seq[PlayerResponse]] shouldEqual response | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,83 @@ | |||||||
|  | package me.arcanis.ffxivbis.http.api.v1 | ||||||
|  |  | ||||||
|  | import akka.actor.ActorRef | ||||||
|  | import akka.http.scaladsl.model.{StatusCodes, Uri} | ||||||
|  | import akka.http.scaladsl.model.headers.{Authorization, BasicHttpCredentials} | ||||||
|  | import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest} | ||||||
|  | import akka.http.scaladsl.server._ | ||||||
|  | import akka.testkit.TestKit | ||||||
|  | import com.typesafe.config.Config | ||||||
|  | import me.arcanis.ffxivbis.{Fixtures, Settings} | ||||||
|  | import me.arcanis.ffxivbis.http.api.v1.json._ | ||||||
|  | import me.arcanis.ffxivbis.service.impl | ||||||
|  | import me.arcanis.ffxivbis.storage.Migration | ||||||
|  | import org.scalatest.{Matchers, WordSpec} | ||||||
|  |  | ||||||
|  | import scala.concurrent.Await | ||||||
|  | import scala.concurrent.duration._ | ||||||
|  | import scala.language.postfixOps | ||||||
|  |  | ||||||
|  | class UserEndpointTest extends WordSpec | ||||||
|  |   with Matchers with ScalatestRouteTest with JsonSupport { | ||||||
|  |  | ||||||
|  |   private val auth: Authorization = | ||||||
|  |     Authorization(BasicHttpCredentials(Fixtures.userAdmin.username, Fixtures.userPassword)) | ||||||
|  |   private val endpoint: Uri = Uri(s"/party/${Fixtures.partyId}/users") | ||||||
|  |   private val timeout: FiniteDuration = 60 seconds | ||||||
|  |   implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(timeout) | ||||||
|  |  | ||||||
|  |   private val storage: ActorRef = system.actorOf(impl.DatabaseImpl.props) | ||||||
|  |   private val route: Route = new UserEndpoint(storage)(timeout).route | ||||||
|  |  | ||||||
|  |   override def testConfig: Config = Settings.withRandomDatabase | ||||||
|  |  | ||||||
|  |   override def beforeAll: Unit = { | ||||||
|  |     Await.result(Migration(system.settings.config), timeout) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   override def afterAll: Unit = { | ||||||
|  |     TestKit.shutdownActorSystem(system) | ||||||
|  |     Settings.clearDatabase(system.settings.config) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   "api v1 users endpoint" must { | ||||||
|  |  | ||||||
|  |     "create a party" in { | ||||||
|  |       val uri = Uri(s"/party/${Fixtures.partyId}/create") | ||||||
|  |       val entity = UserResponse.fromUser(Fixtures.userAdmin).copy(password = Fixtures.userPassword) | ||||||
|  |       println(entity) | ||||||
|  |  | ||||||
|  |       Put(uri, entity) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.Created | ||||||
|  |         responseAs[String] shouldEqual "" | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     "add user" in { | ||||||
|  |       val entity = UserResponse.fromUser(Fixtures.userGet).copy(password = Fixtures.userPassword2) | ||||||
|  |  | ||||||
|  |       Post(endpoint, entity).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.Accepted | ||||||
|  |         responseAs[String] shouldEqual "" | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     "get users" in { | ||||||
|  |       val party = Seq(Fixtures.userAdmin, Fixtures.userGet) | ||||||
|  |         .map(user => user.username -> Some(user.permission)).toMap | ||||||
|  |  | ||||||
|  |       Get(endpoint).withHeaders(auth) ~> route ~> check { | ||||||
|  |         status shouldEqual StatusCodes.OK | ||||||
|  |  | ||||||
|  |         val users = responseAs[Seq[UserResponse]] | ||||||
|  |         users.map(_.partyId).distinct shouldEqual Seq(Fixtures.partyId) | ||||||
|  |         users.map(user => user.username -> user.permission).toMap shouldEqual party | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     "remove user" in { | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								test.sbt
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								test.sbt
									
									
									
									
									
								
							| @ -2,3 +2,5 @@ libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.8" % "test" | |||||||
| libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % "test" | libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % "test" | ||||||
|  |  | ||||||
| libraryDependencies += "com.typesafe.akka" %% "akka-testkit" % "2.5.26" % "test" | libraryDependencies += "com.typesafe.akka" %% "akka-testkit" % "2.5.26" % "test" | ||||||
|  | libraryDependencies += "com.typesafe.akka" %% "akka-stream-testkit" % "2.5.26" % "test" | ||||||
|  | libraryDependencies += "com.typesafe.akka" %% "akka-http-testkit" % "10.1.10" % "test" | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user