You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

163 lines
6.4 KiB

package controllers
import com.alexitc.playsonify.core.ApplicationResult
import com.alexitc.playsonify.models.ordering.FieldOrdering
import com.alexitc.playsonify.models.pagination.{Count, PaginatedQuery, PaginatedResult}
import com.alexitc.playsonify.play.PublicErrorRenderer
import com.xsn.explorer.data.{BalanceBlockingDataHandler, TransactionBlockingDataHandler}
import com.xsn.explorer.helpers.{BalanceDummyDataHandler, DataHelper, TransactionDummyDataHandler}
import com.xsn.explorer.models._
import com.xsn.explorer.models.fields.TransactionField
import com.xsn.explorer.models.persisted.{Balance, Transaction}
import com.xsn.explorer.models.values.{Address, _}
import com.xsn.explorer.util.Extensions.BigDecimalExt
import controllers.common.MyAPISpec
import org.scalactic.Good
import play.api.inject.bind
import play.api.libs.json.JsValue
import play.api.test.Helpers._
class AddressesControllerSpec extends MyAPISpec {
import DataHelper._
val addressWithBalance = createAddress("XeNEPsgeWqNbrEGEN5vqv4wYcC3qQrqNyp")
val addressBalance = Balance(addressWithBalance, spent = 100, received = 200)
val addressForUtxos = DataHelper.createAddress("XeNEPsgeWqNbrEGEN5vqv4wYcC3qQrqNyp")
val utxosResponse = List(
Transaction.Output(
address = createAddress("XeNEPsgeWqNbrEGEN5vqv4wYcC3qQrqNyp"),
index = 0,
value = BigDecimal("1500000000000").fromSatoshis,
script = HexString.from("76a914285b6f1ccacea0059ff5393cb4eb2f0569e2b3e988ac").get,
txid = createTransactionId("ea837f2011974b6a1a2fa077dc33684932c514a4ec6febc10e1a19ebe1336539")
),
Transaction.Output(
address = createAddress("XeNEPsgeWqNbrEGEN5vqv4wYcC3qQrqNyp"),
index = 3,
value = BigDecimal("2250000000").fromSatoshis,
script = HexString.from("76a914285b6f1ccacea0059ff5393cb4eb2f0569e2b3e988ac").get,
txid = createTransactionId("96a06b802d1c15818a42aa9b46dd2e236cde746000d35f74d3eb940ab9d5694d")
)
)
val addressForTransactions = createAddress("XxQ7j37LfuXgsLd5DZAwFKhT3s2ZMkW86F")
val addressTransaction = TransactionWithValues(
createTransactionId("92c51e4fe89466faa734d6207a7ef6115fa1dd33f7156b006fafc6bb85a79eb8"),
createBlockhash("ad22f0dcea2fdaa357aac6eab00695cf07b487e34113598909f625c24629c981"),
12312312L,
Size(1000),
sent = 50,
received = 200)
private val customTransactionDataHandler = new TransactionDummyDataHandler {
override def getBy(address: Address, paginatedQuery: PaginatedQuery, ordering: FieldOrdering[TransactionField]): ApplicationResult[PaginatedResult[TransactionWithValues]] = {
if (address == addressForTransactions) {
Good(PaginatedResult(paginatedQuery.offset, paginatedQuery.limit, Count(1), List(addressTransaction)))
} else {
Good(PaginatedResult(paginatedQuery.offset, paginatedQuery.limit, Count(0), List.empty))
}
}
override def getUnspentOutputs(address: Address): ApplicationResult[List[Transaction.Output]] = {
if (address == addressForUtxos) {
Good(utxosResponse)
} else {
super.getUnspentOutputs(address)
}
}
}
private val customBalanceDataHandler = new BalanceDummyDataHandler {
override def getBy(address: Address): ApplicationResult[Balance] = {
if (address == addressWithBalance) {
Good(addressBalance)
} else {
Good(Balance(address))
}
}
}
override val application = guiceApplicationBuilder
.overrides(bind[TransactionBlockingDataHandler].to(customTransactionDataHandler))
.overrides(bind[BalanceBlockingDataHandler].to(customBalanceDataHandler))
.build()
"GET /addresses/:address" should {
def url(address: String) = s"/addresses/$address"
"retrieve address information" in {
val address = addressWithBalance
val response = GET(url(address.string))
status(response) mustEqual OK
val json = contentAsJson(response)
(json \ "spent").as[BigDecimal] mustEqual addressBalance.spent
(json \ "received").as[BigDecimal] mustEqual addressBalance.received
}
"fail on bad address format" in {
val address = "XnH3bC9NruJ4wnu4Dgi8F"
val response = GET(url(address))
status(response) mustEqual BAD_REQUEST
val json = contentAsJson(response)
val errorList = (json \ "errors").as[List[JsValue]]
errorList.size mustEqual 1
val error = errorList.head
(error \ "type").as[String] mustEqual PublicErrorRenderer.FieldValidationErrorType
(error \ "field").as[String] mustEqual "address"
}
}
"GET /addresses/:address/utxos" should {
def url(address: String) = s"/addresses/$address/utxos"
def matches(json: JsValue, output: Transaction.Output) = {
(json \ "address").as[String] mustEqual output.address.map(_.string).getOrElse("")
(json \ "txid").as[String] mustEqual output.txid.string
(json \ "outputIndex").as[Int] mustEqual output.index
(json \ "script").as[String] mustEqual output.script.string
(json \ "satoshis").as[BigDecimal] mustEqual BigDecimal(output.value.toSatoshis)
}
"return an array with the result" in {
val response = GET(url(addressForUtxos.string))
status(response) mustEqual OK
val result = contentAsJson(response).as[List[JsValue]]
result.zip(utxosResponse).foreach { case (json, output) => matches(json, output) }
}
}
"GET /addresses/:address/transactions" should {
def url(address: String, offset: Int, limit: Int) = s"/addresses/$address/transactions?offset=$offset&limit=$limit"
"return the transactions where the address was involved" in {
val offset = 0
val limit = 5
val response = GET(url(addressForTransactions.string, offset, limit))
status(response) mustEqual OK
val json = contentAsJson(response)
(json \ "offset").as[Int] mustEqual offset
(json \ "limit").as[Int] mustEqual limit
(json \ "total").as[Int] mustEqual 1
val data = (json \ "data").as[List[JsValue]]
data.size mustEqual 1
val item = data.head
(item \ "id").as[String] mustEqual addressTransaction.id.string
(item \ "blockhash").as[String] mustEqual addressTransaction.blockhash.string
(item \ "time").as[Long] mustEqual addressTransaction.time
(item \ "size").as[Int] mustEqual addressTransaction.size.int
(item \ "sent").as[BigDecimal] mustEqual addressTransaction.sent
(item \ "received").as[BigDecimal] mustEqual addressTransaction.received
}
}
}