Skip to content

Commit 2e45d6d

Browse files
committed
Add support to withdrawals in web UI
New form alongside deposits to allow withdrawals so that submitting the form to the correct endpoint is easier. Also, generalise how they are handled as they both received the same inputs and give back the same output type. Remove support for filtering tests that are not yet implemented.
1 parent 213b1ec commit 2e45d6d

7 files changed

Lines changed: 24 additions & 23 deletions

File tree

domain/src/test/kotlin/lmirabal/bank/BankServiceTest.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@ import lmirabal.bank.data.InMemoryBankAccountRepository
66
import lmirabal.bank.model.Amount
77
import lmirabal.bank.model.BankAccount
88
import lmirabal.bank.model.BankAccountId
9-
import org.junit.jupiter.api.Tag
109
import org.junit.jupiter.api.Test
1110

12-
@Tag("ImplementationReady")
1311
class BankServiceTest : BankTest() {
1412
private val idFactory = RecordingIdFactory()
1513
override val bank = BankService(InMemoryBankAccountRepository(), idFactory)

domain/src/testFixtures/kotlin/lmirabal/bank/BankTest.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import com.natpryce.hamkrest.assertion.assertThat
44
import com.natpryce.hamkrest.equalTo
55
import lmirabal.bank.model.Amount
66
import org.junit.jupiter.api.Test
7-
import org.junit.jupiter.api.condition.EnabledIf
8-
import org.junit.jupiter.api.extension.ExtensionContext
97

108
abstract class BankTest {
119
abstract val bank: Bank
@@ -30,7 +28,6 @@ abstract class BankTest {
3028
assertThat(updatedAccount.balance, equalTo(Amount(300)))
3129
}
3230

33-
@EnabledIf("implementationReady")
3431
@Test
3532
fun `withdraws from account`() {
3633
val bankAccount = bank.createAccount()
@@ -40,6 +37,4 @@ abstract class BankTest {
4037

4138
assertThat(updatedAccount.balance, equalTo(Amount(100)))
4239
}
43-
44-
fun implementationReady(context: ExtensionContext) = "ImplementationReady" in context.tags
4540
}

http/src/test/kotlin/lmirabal/bank/http/BankHttpIntegrationTest.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ import org.http4k.server.SunHttp
99
import org.http4k.server.asServer
1010
import org.junit.jupiter.api.AfterEach
1111
import org.junit.jupiter.api.BeforeEach
12-
import org.junit.jupiter.api.Tag
1312

14-
@Tag("ImplementationReady")
1513
class BankHttpIntegrationTest : BankTest() {
1614
private val server = bankHttp().asServer(SunHttp())
1715
override val bank = BankHttpClient(
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package lmirabal.bank.http
22

33
import lmirabal.bank.BankTest
4-
import org.junit.jupiter.api.Tag
54

6-
@Tag("ImplementationReady")
75
class BankHttpTest : BankTest() {
86
override val bank = BankHttpClient(bankHttp())
97
}

web/src/main/kotlin/lmirabal/bank/web/BankWeb.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import org.http4k.core.ContentType.Companion.TEXT_HTML
99
import org.http4k.core.HttpHandler
1010
import org.http4k.core.Method.GET
1111
import org.http4k.core.Method.POST
12+
import org.http4k.core.Request
1213
import org.http4k.core.Response
1314
import org.http4k.core.Status
1415
import org.http4k.core.Status.Companion.SEE_OTHER
@@ -32,7 +33,8 @@ fun bankWeb(bank: Bank): HttpHandler {
3233
POST to CreateAccount(bank),
3334
GET to ListAccounts(bank)
3435
),
35-
"/{id}/deposit" bind POST to DepositAmount(bank)
36+
"/{id}/deposit" bind POST to ChangeBalance(bank) { id, amount -> deposit(id, amount) },
37+
"/{id}/withdraw" bind POST to ChangeBalance(bank) { id, amount -> withdraw(id, amount) },
3638
)
3739
}
3840

@@ -56,16 +58,17 @@ object ListAccounts {
5658

5759
}
5860

59-
object DepositAmount {
61+
class ChangeBalance(private val bank: Bank, private val action: Bank.(BankAccountId, Amount) -> BankAccount) :
62+
HttpHandler {
6063
private val amountField = FormField.long().map { majorUnits -> majorUnits.toAmount() }.required("amount")
6164
private val formBody = Body.webForm(Validator.Feedback, amountField).toLens()
6265

63-
operator fun invoke(bank: Bank): HttpHandler = { request ->
66+
override fun invoke(request: Request): Response {
6467
val id = request.path("id") ?: throw Exception("Bank account id must be present")
6568
val form = formBody(request)
6669
val amount = amountField(form)
67-
bank.deposit(BankAccountId(UUID.fromString(id)), amount)
68-
Response(SEE_OTHER).header("location", "/")
70+
action(bank, BankAccountId(UUID.fromString(id)), amount)
71+
return Response(SEE_OTHER).header("location", "/")
6972
}
7073

7174
private fun Long.toAmount() = Amount(

web/src/main/resources/lmirabal/bank/web/BankAccountListView.hbs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,14 @@
3737
<td>{{id}}</td>
3838
<td>{{balance}}</td>
3939
<td>
40-
<form method="POST" action="/{{id}}/deposit">
40+
<form id="deposit-form" method="POST" action="/{{id}}/deposit">
4141
<input type="number" id="amount" name="amount"/>
4242
<button id="deposit">Deposit</button>
4343
</form>
44+
<form id="withdraw-form" method="POST" action="/{{id}}/withdraw">
45+
<input type="number" id="amount" name="amount"/>
46+
<button id="withdraw">Withdraw</button>
47+
</form>
4448
</td>
4549
</tr>
4650
{{/accounts}}

web/src/test/kotlin/lmirabal/bank/web/BankWebTest.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,20 @@ class BankWebDriver(web: HttpHandler) : Bank {
5454
}
5555

5656
override fun deposit(id: BankAccountId, amount: Amount): BankAccount {
57-
val row = driver.getTableRows().first { row -> row.getBankAccountId() == id }
58-
59-
row.getElement(By.id("amount")).sendKeys(amount.format())
60-
row.getElement(By.id("deposit")).submit()
61-
return driver.getBankAccounts().first { account -> account.id == id }
57+
return changeBalance("deposit", id, amount)
6258
}
6359

6460
override fun withdraw(id: BankAccountId, amount: Amount): BankAccount {
65-
TODO("Not yet implemented")
61+
return changeBalance("withdraw", id, amount)
62+
}
63+
64+
private fun changeBalance(actionId: String, id: BankAccountId, amount: Amount): BankAccount {
65+
val row = driver.getTableRows().first { row -> row.getBankAccountId() == id }
66+
67+
val form = row.getElement(By.id("$actionId-form"))
68+
form.getElement(By.id("amount")).sendKeys(amount.format())
69+
form.getElement(By.id(actionId)).submit()
70+
return driver.getBankAccounts().first { account -> account.id == id }
6671
}
6772

6873
private fun WebElement.getBankAccountId(): BankAccountId {

0 commit comments

Comments
 (0)