package ltd.lulz import java.math.BigDecimal import java.util.UUID import ltd.lulz.model.Transaction import ltd.lulz.model.Transfer import ltd.lulz.test.container.PostgresTestContainer import org.assertj.core.api.SoftAssertions import org.assertj.core.api.junit.jupiter.InjectSoftAssertions import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT import org.springframework.boot.test.web.server.LocalServerPort import org.springframework.http.HttpStatus.BAD_REQUEST import org.springframework.http.HttpStatus.CREATED import org.springframework.http.HttpStatus.NOT_ACCEPTABLE import org.springframework.http.HttpStatus.NOT_FOUND import org.springframework.test.web.reactive.server.WebTestClient @PostgresTestContainer @SpringBootTest(webEnvironment = RANDOM_PORT) @ExtendWith(SoftAssertionsExtension::class) class TransactionEndpoints { @InjectSoftAssertions lateinit var softly: SoftAssertions @LocalServerPort var port: Int = 0 lateinit var webClient: WebTestClient @BeforeEach fun setup() { webClient = WebTestClient.bindToServer().baseUrl("http://localhost:$port").build() } @Nested inner class DepositTest { @Test fun `deposit - success`() { // given val request = Transaction.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000001"), amount = BigDecimal.valueOf(1.00), ) // when val result = webClient.post() .uri("/deposit") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(CREATED) } @Test fun `deposit - fail amount to small`() { // given val request = Transaction.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000001"), amount = BigDecimal.valueOf(0.009), ) // when val result = webClient.post() .uri("/deposit") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(BAD_REQUEST) } @Test fun `deposit - fail account not found`() { // given val request = Transaction.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000000"), amount = BigDecimal.valueOf(0.01), ) // when val result = webClient.post() .uri("/deposit") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(NOT_FOUND) } } @Nested inner class WithdrawalTest { @Test fun `deposit - success`() { // given val request = Transaction.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000001"), amount = BigDecimal.valueOf(1.00), ) // when val result = webClient.post() .uri("/withdrawal") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(CREATED) } @Test fun `deposit - fail amount to small`() { // given val request = Transaction.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000001"), amount = BigDecimal.valueOf(0.009), ) // when val result = webClient.post() .uri("/withdrawal") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(BAD_REQUEST) } @Test fun `deposit - fail account not found`() { // given val request = Transaction.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000000"), amount = BigDecimal.valueOf(1.00), ) // when val result = webClient.post() .uri("/withdrawal") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(NOT_FOUND) } @Test fun `deposit - fail insufficient funds`() { // given val request = Transaction.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000001"), amount = BigDecimal.valueOf(100.00), ) // when val result = webClient.post() .uri("/withdrawal") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(NOT_ACCEPTABLE) } } @Nested inner class TransferTest { @Test fun `deposit - success`() { // given val request = Transfer.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000001"), receiver = UUID.fromString("00000000-0000-7000-0000-000000000002"), amount = BigDecimal.valueOf(1.00), ) // when val result = webClient.post() .uri("/transfer") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(CREATED) } @Test fun `deposit - fail same account`() { // given val request = Transfer.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000001"), receiver = UUID.fromString("00000000-0000-7000-0000-000000000001"), amount = BigDecimal.valueOf(1.00), ) // when val result = webClient.post() .uri("/transfer") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(BAD_REQUEST) } @Test fun `deposit - fail amount to small`() { // given val request = Transfer.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000001"), receiver = UUID.fromString("00000000-0000-7000-0000-000000000002"), amount = BigDecimal.valueOf(0.009), ) // when val result = webClient.post() .uri("/transfer") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(BAD_REQUEST) } @Test fun `deposit - fail account not found`() { // given val request = Transfer.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000000"), receiver = UUID.fromString("00000000-0000-7000-0000-000000000002"), amount = BigDecimal.valueOf(1.00), ) // when val result = webClient.post() .uri("/transfer") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(NOT_FOUND) } @Test fun `deposit - fail receiver not found`() { // given val request = Transfer.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000001"), receiver = UUID.fromString("00000000-0000-7000-0000-000000000000"), amount = BigDecimal.valueOf(1.00), ) // when val result = webClient.post() .uri("/transfer") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(NOT_FOUND) } @Test fun `deposit - fail insufficient funds`() { // given val request = Transfer.Request( account = UUID.fromString("00000000-0000-7000-0000-000000000001"), receiver = UUID.fromString("00000000-0000-7000-0000-000000000002"), amount = BigDecimal.valueOf(100.00), ) // when val result = webClient.post() .uri("/transfer") .bodyValue(request) .exchange() // then result.expectStatus().isEqualTo(NOT_ACCEPTABLE) } } }