more tests

This commit is contained in:
Evgenii Alekseev 2019-10-26 19:44:51 +03:00
parent b228595a1b
commit 4cdcd80d51
27 changed files with 345 additions and 87 deletions

View File

@ -11,8 +11,7 @@ package me.arcanis.ffxivbis.http
import akka.actor.ActorRef import akka.actor.ActorRef
import akka.pattern.ask import akka.pattern.ask
import akka.util.Timeout import akka.util.Timeout
import me.arcanis.ffxivbis.models.{Player, PlayerId} import me.arcanis.ffxivbis.models.{Party, Player, PlayerId}
import me.arcanis.ffxivbis.service.Party
import me.arcanis.ffxivbis.service.impl.{DatabaseBiSHandler, DatabasePartyHandler} import me.arcanis.ffxivbis.service.impl.{DatabaseBiSHandler, DatabasePartyHandler}
import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.{ExecutionContext, Future}

View File

@ -15,7 +15,7 @@ case class PieceResponse(
@Schema(description = "is piece tome gear", required = true) isTome: Boolean, @Schema(description = "is piece tome gear", required = true) isTome: Boolean,
@Schema(description = "job name to which piece belong or AnyJob", required = true, example = "DNC") job: String, @Schema(description = "job name to which piece belong or AnyJob", required = true, example = "DNC") job: String,
@Schema(description = "piece name", required = true, example = "body") piece: String) { @Schema(description = "piece name", required = true, example = "body") piece: String) {
def toPiece: Piece = Piece(piece, isTome, Job.fromString(job)) def toPiece: Piece = Piece(piece, isTome, Job.withName(job))
} }
object PieceResponse { object PieceResponse {

View File

@ -16,5 +16,5 @@ case class PlayerIdResponse(
@Schema(description = "job name", required = true, example = "DNC") job: String, @Schema(description = "job name", required = true, example = "DNC") job: String,
@Schema(description = "player nick name", required = true, example = "Siuan Sanche") nick: String) { @Schema(description = "player nick name", required = true, example = "Siuan Sanche") nick: String) {
def withPartyId(partyId: String): PlayerId = def withPartyId(partyId: String): PlayerId =
PlayerId(partyId, Job.fromString(job), nick) PlayerId(partyId, Job.withName(job), nick)
} }

View File

@ -20,7 +20,7 @@ case class PlayerResponse(
@Schema(description = "link to best in slot", example = "https://ffxiv.ariyala.com/19V5R") link: Option[String], @Schema(description = "link to best in slot", example = "https://ffxiv.ariyala.com/19V5R") link: Option[String],
@Schema(description = "player loot priority") priority: Option[Int]) { @Schema(description = "player loot priority") priority: Option[Int]) {
def toPlayer: Player = def toPlayer: Player =
Player(partyId, Job.fromString(job), nick, Player(partyId, Job.withName(job), nick,
BiS(bis.getOrElse(Seq.empty).map(_.toPiece)), loot.getOrElse(Seq.empty).map(_.toPiece), BiS(bis.getOrElse(Seq.empty).map(_.toPiece)), loot.getOrElse(Seq.empty).map(_.toPiece),
link, priority.getOrElse(0)) link, priority.getOrElse(0))
} }

View File

@ -14,8 +14,7 @@ import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server._ import akka.http.scaladsl.server._
import akka.util.Timeout import akka.util.Timeout
import me.arcanis.ffxivbis.http.UserHelper import me.arcanis.ffxivbis.http.UserHelper
import me.arcanis.ffxivbis.models.{Permission, User} import me.arcanis.ffxivbis.models.{Party, Permission, User}
import me.arcanis.ffxivbis.service.Party
class IndexView(storage: ActorRef)(implicit timeout: Timeout) class IndexView(storage: ActorRef)(implicit timeout: Timeout)
extends UserHelper(storage) { extends UserHelper(storage) {

View File

@ -92,7 +92,7 @@ object PlayerView {
form(action:=s"/party/$partyId/players", method:="post")( form(action:=s"/party/$partyId/players", method:="post")(
input(name:="nick", id:="nick", placeholder:="nick", title:="nick", `type`:="nick"), input(name:="nick", id:="nick", placeholder:="nick", title:="nick", `type`:="nick"),
select(name:="job", id:="job", title:="job") select(name:="job", id:="job", title:="job")
(for (job <- Job.groupAll) yield option(job.toString)), (for (job <- Job.jobs) yield option(job.toString)),
input(name:="link", id:="link", placeholder:="player bis link", title:="link", `type`:="text"), input(name:="link", id:="link", placeholder:="player bis link", title:="link", `type`:="text"),
input(name:="prioiry", id:="priority", placeholder:="priority", title:="priority", `type`:="number", value:="0"), input(name:="prioiry", id:="priority", placeholder:="priority", title:="priority", `type`:="number", value:="0"),
input(name:="action", id:="action", `type`:="hidden", value:="add"), input(name:="action", id:="action", `type`:="hidden", value:="add"),

View File

@ -76,5 +76,5 @@ object BiS {
def apply(): BiS = BiS(Seq.empty) def apply(): BiS = BiS(Seq.empty)
def apply(pieces: Seq[Piece]): BiS = def apply(pieces: Seq[Piece]): BiS =
BiS(pieces.map { piece => piece.piece -> Some(piece) }.toMap) BiS(pieces.map(piece => piece.piece -> Some(piece)).toMap)
} }

View File

@ -9,65 +9,95 @@
package me.arcanis.ffxivbis.models package me.arcanis.ffxivbis.models
object Job { object Job {
sealed trait Job sealed trait RightSide
object AccessoriesDex extends RightSide
object AccessoriesInt extends RightSide
object AccessoriesMnd extends RightSide
object AccessoriesStr extends RightSide
object AccessoriesVit extends RightSide
sealed trait LeftSide
object BodyCasters extends LeftSide
object BodyDrgs extends LeftSide
object BodyHealers extends LeftSide
object BodyMnks extends LeftSide
object BodyNins extends LeftSide
object BodyTanks extends LeftSide
object BodyRanges extends LeftSide
sealed trait Job {
def leftSide: LeftSide
def rightSide: RightSide
// conversion to string to avoid recursion
override def equals(obj: Any): Boolean = {
def canEqual(obj: Any): Boolean = obj.isInstanceOf[Job]
def equality(objRepr: String): Boolean = objRepr match {
case _ if objRepr == AnyJob.toString => true
case _ if this.toString == AnyJob.toString => true
case _ => this.toString == obj.toString
}
canEqual(obj) && equality(obj.toString)
}
}
case object AnyJob extends Job { case object AnyJob extends Job {
override def equals(obj: Any): Boolean = obj match { val leftSide: LeftSide = null
case Job => true val rightSide: RightSide = null
case _ => false
}
} }
case object PLD extends Job trait Casters extends Job {
case object WAR extends Job val leftSide: LeftSide = BodyCasters
case object DRK extends Job val rightSide: RightSide = AccessoriesInt
case object GNB extends Job
case object WHM extends Job
case object SCH extends Job
case object AST extends Job
case object MNK extends Job
case object DRG extends Job
case object NIN extends Job
case object SAM extends Job
case object BRD extends Job
case object MCH extends Job
case object DNC extends Job
case object BLM extends Job
case object SMN extends Job
case object RDM extends Job
def groupAccessoriesDex: Seq[Job.Job] = groupRanges :+ NIN
def groupAccessoriesStr: Seq[Job.Job] = groupMnk :+ DRG
def groupAll: Seq[Job.Job] = groupCasters ++ groupHealers ++ groupRanges ++ groupTanks
def groupCasters: Seq[Job.Job] = Seq(BLM, SMN, RDM)
def groupHealers: Seq[Job.Job] = Seq(WHM, SCH, AST)
def groupMnk: Seq[Job.Job] = Seq(MNK, SAM)
def groupRanges: Seq[Job.Job] = Seq(BRD, MCH, DNC)
def groupTanks: Seq[Job.Job] = Seq(PLD, WAR, DRK, GNB)
def groupFull: Seq[Seq[Job.Job]] = Seq(groupCasters, groupHealers, groupMnk, groupRanges, groupTanks)
def groupRight: Seq[Seq[Job.Job]] = Seq(groupAccessoriesDex, groupAccessoriesStr)
def fromString(job: String): Job.Job = groupAll.find(_.toString == job.toUpperCase).orNull
def hasSameLoot(left: Job, right: Job, piece: Piece): Boolean = {
def isAccessory(piece: Piece): Boolean = piece match {
case _: PieceAccessory => true
case _ => false
} }
def isWeapon(piece: Piece): Boolean = piece match { trait Healers extends Job {
case _: PieceWeapon => true val leftSide: LeftSide = BodyHealers
case _ => false val rightSide: RightSide = AccessoriesMnd
}
trait Mnks extends Job {
val leftSide: LeftSide = BodyMnks
val rightSide: RightSide = AccessoriesStr
}
trait Tanks extends Job {
val leftSide: LeftSide = BodyTanks
val rightSide: RightSide = AccessoriesVit
}
trait Ranges extends Job {
val leftSide: LeftSide = BodyRanges
val rightSide: RightSide = AccessoriesDex
} }
if (left == right) true case object PLD extends Tanks
else if (isWeapon(piece)) false case object WAR extends Tanks
else if (groupFull.exists(group => group.contains(left) && group.contains(right))) true case object DRK extends Tanks
else if (isAccessory(piece) && groupRight.exists(group => group.contains(left) && group.contains(right))) true case object GNB extends Tanks
else false
case object WHM extends Healers
case object SCH extends Healers
case object AST extends Healers
case object MNK extends Mnks
case object DRG extends Job {
val leftSide: LeftSide = BodyDrgs
val rightSide: RightSide = AccessoriesStr
} }
case object NIN extends Job {
val leftSide: LeftSide = BodyNins
val rightSide: RightSide = AccessoriesDex
}
case object SAM extends Mnks
case object BRD extends Ranges
case object MCH extends Ranges
case object DNC extends Ranges
case object BLM extends Casters
case object SMN extends Casters
case object RDM extends Casters
lazy val jobs: Seq[Job] =
Seq(PLD, WAR, DRK, GNB, WHM, SCH, AST, MNK, DRG, NIN, SAM, BRD, MCH, DNC, BLM, SMN, RDM)
def withName(job: String): Job.Job = jobs.find(_.toString == job.toUpperCase).getOrElse(AnyJob)
} }

View File

@ -6,20 +6,18 @@
* *
* License: 3-clause BSD, see https://opensource.org/licenses/BSD-3-Clause * License: 3-clause BSD, see https://opensource.org/licenses/BSD-3-Clause
*/ */
package me.arcanis.ffxivbis.service package me.arcanis.ffxivbis.models
import com.typesafe.config.Config import com.typesafe.config.Config
import com.typesafe.scalalogging.StrictLogging import com.typesafe.scalalogging.StrictLogging
import me.arcanis.ffxivbis.models.{BiS, Loot, Piece, Player, PlayerId} import me.arcanis.ffxivbis.service.LootSelector
import scala.jdk.CollectionConverters._ import scala.jdk.CollectionConverters._
import scala.util.Random import scala.util.Random
case class Party(partyId: String, config: Config, players: Map[PlayerId, Player]) case class Party(partyId: String, rules: Seq[String], players: Map[PlayerId, Player])
extends StrictLogging { extends StrictLogging {
require(players.keys.forall(_.partyId == partyId), "party id must be same")
private val rules =
config.getStringList("me.arcanis.ffxivbis.settings.priority").asScala.toSeq
def getPlayers: Seq[Player] = players.values.toSeq def getPlayers: Seq[Player] = players.values.toSeq
def player(playerId: PlayerId): Option[Player] = players.get(playerId) def player(playerId: PlayerId): Option[Player] = players.get(playerId)
@ -38,8 +36,11 @@ case class Party(partyId: String, config: Config, players: Map[PlayerId, Player]
} }
object Party { object Party {
private def getRules(config: Config): Seq[String] =
config.getStringList("me.arcanis.ffxivbis.settings.priority").asScala.toSeq
def apply(partyId: Option[String], config: Config): Party = def apply(partyId: Option[String], config: Config): Party =
new Party(partyId.getOrElse(randomPartyId), config, Map.empty) new Party(partyId.getOrElse(randomPartyId), getRules(config), Map.empty)
def apply(partyId: String, config: Config, def apply(partyId: String, config: Config,
players: Map[Long, Player], bis: Seq[Loot], loot: Seq[Loot]): Party = { players: Map[Long, Player], bis: Seq[Loot], loot: Seq[Loot]): Party = {
@ -51,7 +52,7 @@ object Party {
.withBiS(bisByPlayer.get(playerId)) .withBiS(bisByPlayer.get(playerId))
.withLoot(lootByPlayer.get(playerId))) .withLoot(lootByPlayer.get(playerId)))
} }
Party(partyId, config, playersWithItems) Party(partyId, getRules(config), playersWithItems)
} }
def randomPartyId: String = Random.alphanumeric.take(20).mkString def randomPartyId: String = Random.alphanumeric.take(20).mkString

View File

@ -104,7 +104,7 @@ object Piece {
case other => throw new Error(s"Unknown item type $other") case other => throw new Error(s"Unknown item type $other")
} }
def available: Seq[String] = Seq("weapon", lazy val available: Seq[String] = Seq("weapon",
"head", "body", "hands", "waist", "legs", "feet", "head", "body", "hands", "waist", "legs", "feet",
"ears", "neck", "wrist", "leftRing", "rightRing") "ears", "neck", "wrist", "leftRing", "rightRing")
} }

View File

@ -15,7 +15,7 @@ case class Player(partyId: String,
loot: Seq[Piece], loot: Seq[Piece],
link: Option[String] = None, link: Option[String] = None,
priority: Int = 0) { priority: Int = 0) {
require(job != Job.AnyJob, "AnyJob is not allowed") require(job ne Job.AnyJob, "AnyJob is not allowed")
val playerId: PlayerId = PlayerId(partyId, job, nick) val playerId: PlayerId = PlayerId(partyId, job, nick)
def withBiS(set: Option[BiS]): Player = set match { def withBiS(set: Option[BiS]): Player = set match {

View File

@ -23,13 +23,13 @@ case class PlayerId(partyId: String, job: Job.Job, nick: String) extends PlayerI
object PlayerId { object PlayerId {
def apply(partyId: String, maybeNick: Option[String], maybeJob: Option[String]): Option[PlayerId] = def apply(partyId: String, maybeNick: Option[String], maybeJob: Option[String]): Option[PlayerId] =
(maybeNick, maybeJob) match { (maybeNick, maybeJob) match {
case (Some(nick), Some(job)) => Try(PlayerId(partyId, Job.fromString(job), nick)).toOption case (Some(nick), Some(job)) => Try(PlayerId(partyId, Job.withName(job), nick)).toOption
case _ => None case _ => None
} }
private val prettyPlayerIdRegex: Regex = "^(.*) \\(([A-Z]{3})\\)$".r private val prettyPlayerIdRegex: Regex = "^(.*) \\(([A-Z]{3})\\)$".r
def apply(partyId: String, player: String): Option[PlayerId] = player match { def apply(partyId: String, player: String): Option[PlayerId] = player match {
case s"${prettyPlayerIdRegex(nick, job)}" => Try(PlayerId(partyId, Job.fromString(job), nick)).toOption case s"${prettyPlayerIdRegex(nick, job)}" => Try(PlayerId(partyId, Job.withName(job), nick)).toOption
case _ => None case _ => None
} }
} }

View File

@ -10,7 +10,7 @@ package me.arcanis.ffxivbis.service
import akka.actor.Actor import akka.actor.Actor
import com.typesafe.scalalogging.StrictLogging import com.typesafe.scalalogging.StrictLogging
import me.arcanis.ffxivbis.models.{Player, PlayerId} import me.arcanis.ffxivbis.models.{Party, Player, PlayerId}
import me.arcanis.ffxivbis.storage.DatabaseProfile import me.arcanis.ffxivbis.storage.DatabaseProfile
import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.{ExecutionContext, Future}

View File

@ -17,7 +17,7 @@ trait BiSProfile { this: DatabaseProfile =>
import dbConfig.profile.api._ import dbConfig.profile.api._
case class BiSRep(playerId: Long, created: Long, piece: String, isTome: Int, job: String) { case class BiSRep(playerId: Long, created: Long, piece: String, isTome: Int, job: String) {
def toLoot: Loot = Loot(playerId, Piece(piece, isTome == 1, Job.fromString(job))) def toLoot: Loot = Loot(playerId, Piece(piece, isTome == 1, Job.withName(job)))
} }
object BiSRep { object BiSRep {
def fromPiece(playerId: Long, piece: Piece) = def fromPiece(playerId: Long, piece: Piece) =

View File

@ -18,7 +18,7 @@ trait LootProfile { this: DatabaseProfile =>
case class LootRep(lootId: Option[Long], playerId: Long, created: Long, piece: String, case class LootRep(lootId: Option[Long], playerId: Long, created: Long, piece: String,
isTome: Int, job: String) { isTome: Int, job: String) {
def toLoot: Loot = Loot(playerId, Piece(piece, isTome == 1, Job.fromString(job))) def toLoot: Loot = Loot(playerId, Piece(piece, isTome == 1, Job.withName(job)))
} }
object LootRep { object LootRep {
def fromPiece(playerId: Long, piece: Piece) = def fromPiece(playerId: Long, piece: Piece) =

View File

@ -19,7 +19,7 @@ trait PlayersProfile { this: DatabaseProfile =>
case class PlayerRep(partyId: String, playerId: Option[Long], created: Long, nick: String, case class PlayerRep(partyId: String, playerId: Option[Long], created: Long, nick: String,
job: String, link: Option[String], priority: Int) { job: String, link: Option[String], priority: Int) {
def toPlayer: Player = def toPlayer: Player =
Player(partyId, Job.fromString(job), nick, BiS(Seq.empty), List.empty, link, priority) Player(partyId, Job.withName(job), nick, BiS(Seq.empty), List.empty, link, priority)
} }
object PlayerRep { object PlayerRep {
def fromPlayer(player: Player, id: Option[Long]): PlayerRep = def fromPlayer(player: Player, id: Option[Long]): PlayerRep =

View File

@ -0,0 +1,55 @@
package me.arcanis.ffxivbis.models
import me.arcanis.ffxivbis.utils.Compare
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
class BiSTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
"bis model" must {
"build set from list" in {
BiS(Fixtures.bis.pieces) shouldEqual Fixtures.bis
}
"has piece" in {
Fixtures.bis.hasPiece(Fixtures.lootBody) shouldEqual true
Fixtures.bis.hasPiece(Fixtures.lootHands) shouldEqual true
}
"has upgrade" in {
Fixtures.bis.hasPiece(Fixtures.lootUpgrade) shouldEqual true
}
"does not have piece" in {
Fixtures.bis.hasPiece(Fixtures.lootLegs) shouldEqual false
}
"create copy with another piece" in {
val bis = BiS(Seq(Fixtures.lootLegs))
val newBis = bis.withPiece(Fixtures.lootHands)
newBis.legs shouldEqual Some(Fixtures.lootLegs)
newBis.hands shouldEqual Some(Fixtures.lootHands)
newBis.pieces.length shouldEqual 2
}
"create copy without piece" in {
val bis = BiS(Seq(Fixtures.lootHands, Fixtures.lootLegs))
val newBis = bis.withoutPiece(Fixtures.lootHands)
newBis.legs shouldEqual Some(Fixtures.lootLegs)
newBis.hands shouldEqual None
newBis.pieces.length shouldEqual 1
}
"ignore upgrade on modification" in {
Fixtures.bis.withPiece(Fixtures.lootUpgrade) shouldEqual Fixtures.bis
Fixtures.bis.withoutPiece(Fixtures.lootUpgrade) shouldEqual Fixtures.bis
}
"return upgrade list" in {
Compare.mapEquals(Fixtures.bis.upgrades, Map[PieceUpgrade, Int](BodyUpgrade -> 2, AccessoryUpgrade -> 4)) shouldEqual true
}
}
}

View File

@ -1,7 +1,5 @@
package me.arcanis.ffxivbis.models package me.arcanis.ffxivbis.models
import me.arcanis.ffxivbis.service.Party
object Fixtures { object Fixtures {
lazy val bis: BiS = BiS( lazy val bis: BiS = BiS(
Seq( Seq(
@ -22,9 +20,15 @@ object Fixtures {
lazy val link: String = "https://ffxiv.ariyala.com/19V5R" lazy val link: String = "https://ffxiv.ariyala.com/19V5R"
lazy val lootBody: Piece = Body(isTome = false, Job.DNC) lazy val lootWeapon: Piece = Weapon(isTome = true, Job.AnyJob)
lazy val lootHands: Piece = Hands(isTome = true, Job.DNC) lazy val lootBody: Piece = Body(isTome = false, Job.AnyJob)
lazy val lootLegs: Piece = Legs(isTome = false, Job.DNC) lazy val lootHands: Piece = Hands(isTome = true, Job.AnyJob)
lazy val lootWaist: Piece = Waist(isTome = true, Job.AnyJob)
lazy val lootLegs: Piece = Legs(isTome = false, Job.AnyJob)
lazy val lootEars: Piece = Ears(isTome = false, Job.AnyJob)
lazy val lootRing: Piece = Ring(isTome = true, Job.AnyJob)
lazy val lootLeftRing: Piece = Ring(isTome = true, Job.AnyJob, "leftRing")
lazy val lootRightRing: Piece = Ring(isTome = true, Job.AnyJob, "rightRing")
lazy val lootUpgrade: Piece = BodyUpgrade lazy val lootUpgrade: Piece = BodyUpgrade
lazy val loot: Seq[Piece] = Seq(lootBody, lootHands, lootLegs, lootUpgrade) lazy val loot: Seq[Piece] = Seq(lootBody, lootHands, lootLegs, lootUpgrade)

View File

@ -0,0 +1,26 @@
package me.arcanis.ffxivbis.models
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
class JobTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
"job model" must {
"create job from string" in {
Job.jobs.foreach { job =>
Job.withName(job.toString) shouldEqual job
}
}
"return AnyJob on unknown job" in {
Job.withName("random string") shouldEqual Job.AnyJob
}
"equal AnyJob to others" in {
Job.jobs.foreach { job =>
Job.AnyJob shouldBe job
}
}
}
}

View File

@ -0,0 +1,51 @@
package me.arcanis.ffxivbis.models
import me.arcanis.ffxivbis.utils.Compare
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
class PartyTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
private val party =
Party(Fixtures.partyId, Seq.empty, Map(Fixtures.playerEmpty.playerId -> Fixtures.playerEmpty))
"party model" must {
"accept player with same party id" in {
noException should be thrownBy
Party(Fixtures.partyId, Seq.empty, Map(Fixtures.playerEmpty.playerId -> Fixtures.playerEmpty))
}
"fail on multiple party ids" in {
val anotherPlayer = Fixtures.playerEmpty.copy(partyId = Fixtures.partyId2)
an [IllegalArgumentException] should be thrownBy
Party(Fixtures.partyId, Seq.empty, Map(anotherPlayer.playerId -> anotherPlayer))
an [IllegalArgumentException] should be thrownBy
Party(Fixtures.partyId, Seq.empty, Map(Fixtures.playerEmpty.playerId -> Fixtures.playerEmpty, anotherPlayer.playerId -> anotherPlayer))
}
"return player list" in {
Compare.seqEquals(party.getPlayers, Seq(Fixtures.playerEmpty)) shouldEqual true
}
"return player" in {
party.player(Fixtures.playerEmpty.playerId) shouldEqual Some(Fixtures.playerEmpty)
}
"return empty on unknown player" in {
party.player(Fixtures.playerEmpty.copy(partyId = Fixtures.partyId2).playerId) shouldEqual None
}
"add new player" in {
val newParty = Party(Fixtures.partyId, Seq.empty, Map.empty)
newParty.withPlayer(Fixtures.playerEmpty) shouldEqual party
}
"reject player with another party id" in {
val anotherPlayer = Fixtures.playerEmpty.copy(partyId = Fixtures.partyId2)
party.withPlayer(anotherPlayer) shouldEqual party
}
}
}

View File

@ -0,0 +1,32 @@
package me.arcanis.ffxivbis.models
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
class PieceTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
"piece model" must {
"convert `isTome` property to string" in {
Fixtures.lootBody.isTomeToString shouldEqual "no"
Fixtures.lootHands.isTomeToString shouldEqual "yes"
}
"return upgrade" in {
Fixtures.lootWeapon.upgrade shouldEqual Some(WeaponUpgrade)
Fixtures.lootBody.upgrade shouldEqual None
Fixtures.lootHands.upgrade shouldEqual Some(BodyUpgrade)
Fixtures.lootWaist.upgrade shouldEqual Some(AccessoryUpgrade)
Fixtures.lootLegs.upgrade shouldEqual None
Fixtures.lootEars.upgrade shouldEqual None
Fixtures.lootLeftRing.upgrade shouldEqual Some(AccessoryUpgrade)
Fixtures.lootRightRing.upgrade shouldEqual Some(AccessoryUpgrade)
}
"build piece from string" in {
Fixtures.bis.pieces.foreach { piece =>
Piece(piece.piece, piece.isTome, piece.job) shouldEqual piece
}
}
}
}

View File

@ -0,0 +1,14 @@
package me.arcanis.ffxivbis.models
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
class PlayerIdTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
"player id model" must {
"be parsed from string" in {
PlayerId(Fixtures.partyId, Fixtures.playerEmpty.playerId.toString) shouldEqual Some(Fixtures.playerEmpty.playerId)
}
}
}

View File

@ -0,0 +1,18 @@
package me.arcanis.ffxivbis.models
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
class PlayerTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
"player model" must {
"add best in slot set" in {
Fixtures.playerEmpty.withBiS(Some(Fixtures.bis)).bis shouldEqual Fixtures.bis
}
"add loot" in {
Fixtures.playerEmpty.withLoot(Some(Fixtures.loot)).loot shouldEqual Fixtures.loot
}
}
}

View File

@ -0,0 +1,24 @@
package me.arcanis.ffxivbis.models
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
class UserTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
"user model" must {
"verify password" in {
Fixtures.userAdmin.verify(Fixtures.userPassword) shouldEqual true
Fixtures.userAdmin.verify(Fixtures.userPassword2) shouldEqual false
}
"verify scope" in {
Permission.values.foreach { permission =>
Fixtures.userAdmin.verityScope(permission) shouldEqual true
}
Permission.values.foreach { permission =>
Fixtures.userGet.verityScope(permission) shouldEqual (permission == Permission.get)
}
}
}
}

View File

@ -2,7 +2,7 @@ package me.arcanis.ffxivbis.service
import akka.actor.ActorSystem import akka.actor.ActorSystem
import akka.testkit.{ImplicitSender, TestKit} import akka.testkit.{ImplicitSender, TestKit}
import me.arcanis.ffxivbis.models.{Fixtures, Settings} import me.arcanis.ffxivbis.models.{Fixtures, Party, Settings}
import me.arcanis.ffxivbis.storage.Migration import me.arcanis.ffxivbis.storage.Migration
import me.arcanis.ffxivbis.utils.Compare import me.arcanis.ffxivbis.utils.Compare
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike} import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}

View File

@ -1,6 +1,11 @@
package me.arcanis.ffxivbis.utils package me.arcanis.ffxivbis.utils
object Compare { object Compare {
def mapEquals[K, T](left: Map[K, T], right: Map[K, T]): Boolean =
left.forall {
case (key, value) => right.contains(key) && right(key) == value
}
def seqEquals[T](left: Seq[T], right: Seq[T]): Boolean = def seqEquals[T](left: Seq[T], right: Seq[T]): Boolean =
left.groupBy(identity).view.mapValues(_.size).forall { left.groupBy(identity).view.mapValues(_.size).forall {
case (key, count) => right.count(_ == key) == count case (key, count) => right.count(_ == key) == count