diff --git a/README.md b/README.md index ab521f8..52318f2 100644 --- a/README.md +++ b/README.md @@ -97,4 +97,37 @@ Keuntungan menerapkan prinsip SOLID Kerugian tidak menerapkan prinsip SOLID - Kode hanya dipahami oleh orang yang menulis kode, orang lain yang membaca kode lebih banyak menghabiskan waktunya dalam memahami kode lama dibanding membuat kode baru - Kode sulit dikelola, sulit menambah fitur, dan tidak fleksibel -- Apabila menemukan error atau bug akan sulit melacak kode penyebabnya \ No newline at end of file +- Apabila menemukan error atau bug akan sulit melacak kode penyebabnya + +## Module 4 + +Menurut saya alur TDD (Test-Driven Development) sudah membantu saya selama melakukan pemograman dalam aplikasi Springboot ini, sebab saya sudah menetapkan ekspektasi output program dari awal, sehingga saat melakukan pemrograman menjadi lebih terarah. + + +F.I.R.S.T. principle or not. If not, explain things that you need to do the next time you create more tests. + +- Fast : sudah terpenuhi karena saya memisahkan tests menjadi unit tests dan functional tests, serta menggunakan stubs contohnya InjectMocks OrderServiceImpl dan Mock orderRepository, sehingga test dapat berjalan dengan cepat +- Isolated/Independent : sudah terpenuhi karena saya sudah set up objek dummy atau mock sebelum test case, contohnya pada `OrderTest.java` terdapat method BeforeEach +```java + @BeforeEach + void setUp() { + this.products = new ArrayList<>(); + + Product product1 = new Product(); + product1.setProductId("eb558e9f-1c39-460e-8860-71af6af63bd6"); + product1.setProductName("Sampo Cap Bambang"); + product1.setProductQuantity(2); + + Product product2 = new Product(); + product2.setProductId("a2c62328-4a37-4664-83c7-f32db8620155"); + product2.setProductName("Sabun Cap Usep"); + product2.setProductQuantity(1); + + this.products.add(product1); + this.products.add(product2); + } +``` + +- Repeatable: sudah terpenuhi karena test yang saya buat sudah terisolasi dan dapat berjalan berkali-kali dengan hasil yang konsisten. +- Self-Validating: sudah terpenuhi karena test saya sudah strict serta menggunakan assertions daripada print secara manual. Namun masih beberapa kekurangan yang dapat diimprove seperti kurangnya pesan dalam tiap assertion dan terlalu banyak assertion dalam satu test method. +- Thorough/Timely: sudah terpenuhi karena test yang saya buat sudah mencover semua happy & unhappy path yang mencankup semua kemungkinan error. \ No newline at end of file diff --git a/src/main/java/id/ac/ui/cs/advprog/eshop/enums/OrderStatus.java b/src/main/java/id/ac/ui/cs/advprog/eshop/enums/OrderStatus.java new file mode 100644 index 0000000..e53526d --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/eshop/enums/OrderStatus.java @@ -0,0 +1,26 @@ +package id.ac.ui.cs.advprog.eshop.enums; + + +import lombok.Getter; + +@Getter +public enum OrderStatus { + WAITING_PAYMENT("WAITING_PAYMENT"), + FAILED("FAILED"), + SUCCESS("SUCCESS"), + CANCELLED("CANCELLED"); + + private final String value; + private OrderStatus (String value) { + this.value = value; + } + + public static boolean contains(String param) { + for (OrderStatus orderStatus : OrderStatus.values()) { + if (orderStatus.name().equals(param)) { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/id/ac/ui/cs/advprog/eshop/enums/PaymentStatus.java b/src/main/java/id/ac/ui/cs/advprog/eshop/enums/PaymentStatus.java new file mode 100644 index 0000000..9d7d881 --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/eshop/enums/PaymentStatus.java @@ -0,0 +1,23 @@ +package id.ac.ui.cs.advprog.eshop.enums; + +import lombok.Getter; + +@Getter +public enum PaymentStatus { + SUCCESS("SUCCESS"), + REJECTED("REJECTED"); + + private final String value; + private PaymentStatus (String value) { + this.value = value; + } + + public static boolean contains(String param) { + for (PaymentStatus paymentStatus : PaymentStatus.values()) { + if (paymentStatus.name().equals(param)) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/id/ac/ui/cs/advprog/eshop/model/Order.java b/src/main/java/id/ac/ui/cs/advprog/eshop/model/Order.java new file mode 100644 index 0000000..3d5d1e0 --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/eshop/model/Order.java @@ -0,0 +1,45 @@ +package id.ac.ui.cs.advprog.eshop.model; + + +import id.ac.ui.cs.advprog.eshop.enums.OrderStatus; +import lombok.Builder; +import lombok.Getter; + +import java.util.List; + +@Builder +@Getter +public class Order { + + String id; + List products; + Long orderTime; + String author; + String status; + + public Order(String id, List products, Long orderTime, String author) { + this.id = id; + this.orderTime = orderTime; + this.author = author; + this.status = OrderStatus.WAITING_PAYMENT.getValue(); + + if (products.isEmpty()){ + throw new IllegalArgumentException(); + } else{ + this.products = products; + } + } + + public Order(String id, List products, Long orderTime, String author, String status) { + this(id, products,orderTime, author); + this.setStatus(status); + } + + public void setStatus(String status){ + if (OrderStatus.contains(status)){ + this.status = status; + } else{ + throw new IllegalArgumentException(); + } + } +} diff --git a/src/main/java/id/ac/ui/cs/advprog/eshop/model/Payment.java b/src/main/java/id/ac/ui/cs/advprog/eshop/model/Payment.java new file mode 100644 index 0000000..ea16a0f --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/eshop/model/Payment.java @@ -0,0 +1,58 @@ +package id.ac.ui.cs.advprog.eshop.model; + +import id.ac.ui.cs.advprog.eshop.enums.OrderStatus; +import id.ac.ui.cs.advprog.eshop.enums.PaymentStatus; +import lombok.Builder; +import lombok.Getter; + + +import java.util.Map; + + +@Getter +public abstract class Payment { + + String id; + Order order; + Map paymentData; + + String status; + + + + public Payment(String id, Order order, Map paymentData) { + this.id = id; + this.order = order; + this.paymentData = paymentData; + + + if (paymentDataIsValid()){ + setStatus("SUCCESS"); + } else{ + setStatus("REJECTED"); + } + } + public Payment(String id, Order order, Map paymentData, String status) { + this.id = id; + this.order = order; + this.paymentData = paymentData; + setStatus(status); + } + public void setStatus(String status){ + if (PaymentStatus.contains(status)){ + this.status = status; + + if (status.equals("SUCCESS")){ + order.setStatus("SUCCESS"); + } else if (status.equals("REJECTED")){ + order.setStatus("FAILED"); + } + + } else{ + throw new IllegalArgumentException(); + } + + } + + abstract boolean paymentDataIsValid(); +} diff --git a/src/main/java/id/ac/ui/cs/advprog/eshop/model/PaymentCashOnDelivery.java b/src/main/java/id/ac/ui/cs/advprog/eshop/model/PaymentCashOnDelivery.java new file mode 100644 index 0000000..1971893 --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/eshop/model/PaymentCashOnDelivery.java @@ -0,0 +1,21 @@ +package id.ac.ui.cs.advprog.eshop.model; + + +import lombok.Builder; + +import java.util.Map; + +public class PaymentCashOnDelivery extends Payment{ + public PaymentCashOnDelivery(String id, Order order, Map paymentData) { + super(id, order, paymentData); + } + + @Override + boolean paymentDataIsValid() { + String address = paymentData.get("address"); + String deliveryFee = paymentData.get("deliveryFee"); + + return address != null && !address.isEmpty() && deliveryFee != null && !deliveryFee.isEmpty(); + } +} + diff --git a/src/main/java/id/ac/ui/cs/advprog/eshop/model/PaymentVoucherCode.java b/src/main/java/id/ac/ui/cs/advprog/eshop/model/PaymentVoucherCode.java new file mode 100644 index 0000000..5d14d4f --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/eshop/model/PaymentVoucherCode.java @@ -0,0 +1,33 @@ +package id.ac.ui.cs.advprog.eshop.model; + +import lombok.Builder; + +import java.util.Map; + +public class PaymentVoucherCode extends Payment{ + public PaymentVoucherCode(String id, Order order, Map paymentData) { + super(id, order, paymentData); + } + + @Override + boolean paymentDataIsValid() { + String voucherCode = paymentData.get("voucherCode"); + if (voucherCode == null || voucherCode.length() != 16 || !voucherCode.startsWith("ESHOP")) { + return false; + } + + int numCharCount = 0; + for (int i = 0; i < voucherCode.length(); i++){ + if (Character.isDigit(voucherCode.charAt(i))){ + numCharCount++; + } + } + + if (numCharCount != 8){ + return false; + } + + + return true; + } +} diff --git a/src/main/java/id/ac/ui/cs/advprog/eshop/repository/OrderRepository.java b/src/main/java/id/ac/ui/cs/advprog/eshop/repository/OrderRepository.java new file mode 100644 index 0000000..c484dd8 --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/eshop/repository/OrderRepository.java @@ -0,0 +1,43 @@ +package id.ac.ui.cs.advprog.eshop.repository; + +import org.springframework.stereotype.Repository; +import id.ac.ui.cs.advprog.eshop.model.Order; + +import java.util.ArrayList; +import java.util.List; + +@Repository +public class OrderRepository { + private List orderData = new ArrayList<>(); + public Order save(Order order) { + int i = 0; + for (Order savedOrder : orderData){ + if (savedOrder.getId().equals(order.getId())){ + orderData.remove(i); + orderData.add(i, order); + return order; + } + i += 1; + } + + orderData.add(order); + return order; + } + public Order findById(String id){ + for (Order savedOrder : orderData){ + if (savedOrder.getId().equals(id)){ + return savedOrder; + } + } + return null; + } + public List findAllByAuthor(String author){ + List result = new ArrayList<>(); + for (Order savedOrder : orderData){ + if (savedOrder.getAuthor().equals(author)){ + result.add(savedOrder); + } + } + return result; + } +} diff --git a/src/main/java/id/ac/ui/cs/advprog/eshop/repository/PaymentRepository.java b/src/main/java/id/ac/ui/cs/advprog/eshop/repository/PaymentRepository.java new file mode 100644 index 0000000..1f3aedc --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/eshop/repository/PaymentRepository.java @@ -0,0 +1,37 @@ +package id.ac.ui.cs.advprog.eshop.repository; + +import id.ac.ui.cs.advprog.eshop.model.Payment; + +import java.util.ArrayList; +import java.util.List; + +public class PaymentRepository { + private List paymentData = new ArrayList<>(); + + public Payment save(Payment payment) { + int i = 0; + for (Payment savedPayment : paymentData){ + if (savedPayment.getId().equals(payment.getId())){ + paymentData.remove(i); + paymentData.add(i, payment); + return payment; + } + i += 1; + } + + paymentData.add(payment); + + return payment; + } + public Payment findById(String id){ + for (Payment savedPayment : paymentData){ + if (savedPayment.getId().equals(id)){ + return savedPayment; + } + } + return null; + } + public List getAllPayment(){ + return paymentData; + } +} diff --git a/src/main/java/id/ac/ui/cs/advprog/eshop/service/OrderService.java b/src/main/java/id/ac/ui/cs/advprog/eshop/service/OrderService.java new file mode 100644 index 0000000..c77abbe --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/eshop/service/OrderService.java @@ -0,0 +1,12 @@ +package id.ac.ui.cs.advprog.eshop.service; + +import id.ac.ui.cs.advprog.eshop.model.Order; + +import java.util.List; + +public interface OrderService { + public Order createOrder (Order order); + public Order updateStatus(String orderId, String status); + public Order findById(String orderId); + public List findAllByAuthor(String author); +} diff --git a/src/main/java/id/ac/ui/cs/advprog/eshop/service/OrderServiceImpl.java b/src/main/java/id/ac/ui/cs/advprog/eshop/service/OrderServiceImpl.java new file mode 100644 index 0000000..de7d259 --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/eshop/service/OrderServiceImpl.java @@ -0,0 +1,43 @@ +package id.ac.ui.cs.advprog.eshop.service; + +import id.ac.ui.cs.advprog.eshop.model.Order; +import id.ac.ui.cs.advprog.eshop.repository.OrderRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.NoSuchElementException; + +@Service +public class OrderServiceImpl implements OrderService { + @Autowired + private OrderRepository orderRepository; + @Override + public Order createOrder(Order order){ + if (orderRepository.findById(order.getId()) == null){ + orderRepository.save(order); + return order; + } + return null; + } + @Override + public Order updateStatus(String orderId, String status){ + Order order = orderRepository.findById(orderId); + if (order != null){ + Order newOrder = new Order(order.getId(), order.getProducts(), + order.getOrderTime(), order.getAuthor(), status); + orderRepository.save(newOrder); + return newOrder; + } else{ + throw new NoSuchElementException(); + } + } + @Override + public List findAllByAuthor(String author){ + return orderRepository.findAllByAuthor(author); + } + @Override + public Order findById(String orderId){ + return orderRepository.findById(orderId); + } +} diff --git a/src/main/java/id/ac/ui/cs/advprog/eshop/service/PaymentService.java b/src/main/java/id/ac/ui/cs/advprog/eshop/service/PaymentService.java new file mode 100644 index 0000000..a7743a0 --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/eshop/service/PaymentService.java @@ -0,0 +1,14 @@ +package id.ac.ui.cs.advprog.eshop.service; + +import id.ac.ui.cs.advprog.eshop.model.Order; +import id.ac.ui.cs.advprog.eshop.model.Payment; + +import java.util.List; +import java.util.Map; + +public interface PaymentService { + public Payment addPayment (String id, Order order, String method, Map paymentData); + public Payment setStatus(Payment payment, String status); + public Payment getPayment(String paymentId); + public List getAllPayments(); +} diff --git a/src/main/java/id/ac/ui/cs/advprog/eshop/service/PaymentServiceImpl.java b/src/main/java/id/ac/ui/cs/advprog/eshop/service/PaymentServiceImpl.java new file mode 100644 index 0000000..77af1f4 --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/eshop/service/PaymentServiceImpl.java @@ -0,0 +1,56 @@ +package id.ac.ui.cs.advprog.eshop.service; + +import id.ac.ui.cs.advprog.eshop.enums.PaymentStatus; +import id.ac.ui.cs.advprog.eshop.model.Order; +import id.ac.ui.cs.advprog.eshop.model.Payment; +import id.ac.ui.cs.advprog.eshop.model.PaymentCashOnDelivery; +import id.ac.ui.cs.advprog.eshop.model.PaymentVoucherCode; +import id.ac.ui.cs.advprog.eshop.repository.PaymentRepository; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +public class PaymentServiceImpl implements PaymentService{ + @Autowired + private PaymentRepository paymentRepository; + + public Payment addPayment (String id, Order order, String method, Map paymentData){ + if (paymentRepository.findById(id) == null){ + + Payment payment; + switch (method){ + case "VOUCHER_CODE": + payment = new PaymentVoucherCode(id, order, paymentData); + break; + case "CASH_ON_DELIVERY": + payment = new PaymentCashOnDelivery(id, order, paymentData); + break; + default: + throw new IllegalArgumentException(); + } + paymentRepository.save(payment); + return payment; + } + return null; + } + public Payment setStatus(Payment payment, String status){ + Payment savedPayment = paymentRepository.findById(payment.getId()); + if (savedPayment != null){ + + savedPayment.setStatus(status); + paymentRepository.save(savedPayment); + return savedPayment; + + }else{ + throw new NoSuchElementException(); + } + } + public Payment getPayment(String paymentId){ + return paymentRepository.findById(paymentId); + } + public List getAllPayments(){ + return paymentRepository.getAllPayment(); + } +} diff --git a/src/test/java/id/ac/ui/cs/advprog/eshop/model/OrderTest.java b/src/test/java/id/ac/ui/cs/advprog/eshop/model/OrderTest.java new file mode 100644 index 0000000..ff59cfb --- /dev/null +++ b/src/test/java/id/ac/ui/cs/advprog/eshop/model/OrderTest.java @@ -0,0 +1,89 @@ +package id.ac.ui.cs.advprog.eshop.model; + + +import id.ac.ui.cs.advprog.eshop.enums.OrderStatus; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class OrderTest { + private List products; + + @BeforeEach + void setUp() { + this.products = new ArrayList<>(); + + Product product1 = new Product(); + product1.setProductId("eb558e9f-1c39-460e-8860-71af6af63bd6"); + product1.setProductName("Sampo Cap Bambang"); + product1.setProductQuantity(2); + + Product product2 = new Product(); + product2.setProductId("a2c62328-4a37-4664-83c7-f32db8620155"); + product2.setProductName("Sabun Cap Usep"); + product2.setProductQuantity(1); + + this.products.add(product1); + this.products.add(product2); + } + + + @Test + void testCreateOrderEmptyProduct() { + this.products.clear(); + + assertThrows(IllegalArgumentException.class, () -> { + Order order = new Order("13652556-012a-4c07-b546-54eb1396d79b", this.products, 1708560000L, "Safira Sudrajat"); + }); + } + + @Test + void testCreateOrderDefaultStatus() { + Order order = new Order("13652556-012a-4c07-b546-54eb1396d79b", this.products, 1708560000L, "Safira Sudrajat"); + + assertSame(this.products, order.getProducts()); + assertEquals(2, order.getProducts().size()); + assertEquals("Sampo Cap Bambang", order.getProducts().get(0).getProductName()); + assertEquals("Sabun Cap Usep", order.getProducts().get(1).getProductName()); + assertEquals("13652556-012a-4c07-b546-54eb1396d79b", order.getId()); + assertEquals(1708560000L, order.getOrderTime()); + assertEquals("Safira Sudrajat", order.getAuthor()); + assertEquals("WAITING_PAYMENT", order.getStatus()); + + } + + + @Test + void testCreateOrderSuccessStatus() { + Order order = new Order("13652556-012a-4c07-b546-54eb1396d79b", + this.products, 1708560000L, "Safira Sudrajat", OrderStatus.SUCCESS.getValue()); + assertEquals(OrderStatus.SUCCESS.getValue(), order.getStatus()); + } + + + @Test + void testCreateOrderInvalidStatus() { + assertThrows (IllegalArgumentException.class, () -> { + Order order = new Order("13652556-012a-4c07-b546-54eb1396d79b", this.products, 1708560000L, "Safira Sudrajat", "MEOW"); + }); + } + + @Test + void testSetStatusToCancelled() { + Order order = new Order("13652556-012a-4c07-b546-54eb1396d79b", this.products, 1708560000L, "Safira Sudrajat"); + order.setStatus(OrderStatus.CANCELLED.getValue()); + assertEquals(OrderStatus.CANCELLED.getValue(), order.getStatus()); + } + + + @Test + void testSetStatusToInvalidStatus() { + Order order = new Order("13652556-012a-4c07-b546-54eb1396d79b", this.products, 1708560000L, "Safira Sudrajat"); + assertThrows(IllegalArgumentException.class, () -> order.setStatus("MEOW")); + } + +} diff --git a/src/test/java/id/ac/ui/cs/advprog/eshop/model/PaymentTest.java b/src/test/java/id/ac/ui/cs/advprog/eshop/model/PaymentTest.java new file mode 100644 index 0000000..af805f9 --- /dev/null +++ b/src/test/java/id/ac/ui/cs/advprog/eshop/model/PaymentTest.java @@ -0,0 +1,178 @@ +package id.ac.ui.cs.advprog.eshop.model; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +class PaymentTest { + private List products; + private List orders; + + @BeforeEach + void setUp() { + + // Setup products + this.products = new ArrayList<>(); + + Product product1 = new Product(); + product1.setProductId("eb558e9f-1c39-460e-8860-71af6af63bd6"); + product1.setProductName("Sampo Cap Bambang"); + product1.setProductQuantity(2); + + Product product2 = new Product(); + product2.setProductId("a2c62328-4a37-4664-83c7-f32db8620155"); + product2.setProductName("Sabun Cap Usep"); + product2.setProductQuantity(1); + + this.products.add(product1); + this.products.add(product2); + + + // Setup orders + Order order1 = new Order("13652556-012a-4c07-b546-54eb1396d79b", this.products, 1708560000L, "Safira Sudrajat"); + Order order2 = new Order("93652556-012a-4c07-b546-54eb1396d79b", this.products, 1708570000L, "Bambang Bambang"); + this.orders = new ArrayList(); + this.orders.add(order1); + this.orders.add(order2); + } + + + // Voucher Code + @Test + void testCreatePaymentSameOrders() { + Map paymentData = new HashMap(); + paymentData.put("voucherCode", "ESHOP1234ABC5678"); + Payment payment = new PaymentVoucherCode("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + assertSame(this.orders.getFirst(), payment.getOrder()); + } + + @Test + void testCreatePaymentVoucherCodeSuccess(){ + Map paymentData = new HashMap(); + paymentData.put("voucherCode", "ESHOP1234ABC5678"); + Payment payment = new PaymentVoucherCode("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + assertEquals("SUCCESS", payment.getStatus()); + } + @Test + void testCreatePaymentVoucherCodeRejectedNot16Characters(){ + Map paymentData = new HashMap(); + paymentData.put("voucherCode", "ESHOP1234ABC56782"); + Payment payment = new PaymentVoucherCode("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + assertEquals("REJECTED", payment.getStatus()); + } + @Test + void testCreatePaymentVoucherCodeRejectedNotStartedWithESHOP(){ + Map paymentData = new HashMap(); + paymentData.put("voucherCode", "ESSHOP1234ABC567"); + Payment payment = new PaymentVoucherCode("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + assertEquals("REJECTED", payment.getStatus()); + } + @Test + void testCreatePaymentVoucherCodeRejectedNotContain8NumericalCharacters(){ + Map paymentData = new HashMap(); + paymentData.put("voucherCode", "ESHOP1234ABC567D"); + Payment payment = new PaymentVoucherCode("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + assertEquals("REJECTED", payment.getStatus()); + } + + @Test + void testCreatePaymentVoucherCodeRejectedNoVocuherCode(){ + Map paymentData = new HashMap(); + Payment payment = new PaymentVoucherCode("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + assertEquals("REJECTED", payment.getStatus()); + } + + + @Test + void testSetStatusPaymentVoucherCodeSuccess(){ + Map paymentData = new HashMap(); + paymentData.put("voucherCode", "ESHOP1234ABC567D"); + Payment payment = new PaymentVoucherCode("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + payment.setStatus("SUCCESS"); + assertEquals("SUCCESS", payment.getOrder().getStatus()); + } + @Test + void testSetStatusPaymentVoucherCodeRejected(){ + Map paymentData = new HashMap(); + paymentData.put("voucherCode", "ESHOP1234ABC567D"); + Payment payment = new PaymentVoucherCode("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + payment.setStatus("REJECTED"); + assertEquals("FAILED", payment.getOrder().getStatus()); + } + + + @Test + void testCreateOrderInvalidStatus() { + Map paymentData = new HashMap(); + paymentData.put("voucherCode", "ESHOP1234ABC567D"); + Payment payment = new PaymentVoucherCode("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + assertThrows (IllegalArgumentException.class, () -> { + payment.setStatus("WKWKWKWK"); + }); + } + + + + // Cash on Delivery + @Test + void testCreatePaymentCashOnDeliverySuccess(){ + Map paymentData = new HashMap(); + paymentData.put("address", "Jalan Anggur"); + paymentData.put("deliveryFee", "12000"); + Payment payment = new PaymentCashOnDelivery("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + assertEquals("SUCCESS", payment.getStatus()); + } + @Test + void testCreatePaymentCashOnDeliveryRejectedMissingAddress(){ + Map paymentData = new HashMap(); + paymentData.put("deliveryFee", "12000"); + Payment payment = new PaymentCashOnDelivery("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + assertEquals("REJECTED", payment.getStatus()); + } + @Test + void testCreatePaymentCashOnDeliveryRejectedMissingDeliveryFee(){ + Map paymentData = new HashMap(); + paymentData.put("address", "Jalan Anggur"); + Payment payment = new PaymentCashOnDelivery("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + assertEquals("REJECTED", payment.getStatus()); + } + + @Test + void testSetStatusPaymentCashOnDeliverySuccess(){ + Map paymentData = new HashMap(); + paymentData.put("address", "Jalan Anggur"); + paymentData.put("deliveryFee", "12000"); + Payment payment = new PaymentCashOnDelivery("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + payment.setStatus("SUCCESS"); + assertEquals("SUCCESS", payment.getOrder().getStatus()); + } + @Test + void testSetStatusPaymentCashOnDeliveryRejected(){ + Map paymentData = new HashMap(); + paymentData.put("address", "Jalan Anggur"); + paymentData.put("deliveryFee", "12000"); + Payment payment = new PaymentCashOnDelivery("6c93d3e2-b009-46ba-9d15-f03d85adc2de", this.orders.getFirst(), paymentData); + + payment.setStatus("REJECTED"); + assertEquals("FAILED", payment.getOrder().getStatus()); + } +} diff --git a/src/test/java/id/ac/ui/cs/advprog/eshop/repository/OrderRepositoryTest.java b/src/test/java/id/ac/ui/cs/advprog/eshop/repository/OrderRepositoryTest.java new file mode 100644 index 0000000..47e69fb --- /dev/null +++ b/src/test/java/id/ac/ui/cs/advprog/eshop/repository/OrderRepositoryTest.java @@ -0,0 +1,109 @@ +package id.ac.ui.cs.advprog.eshop.repository; + + +import id.ac.ui.cs.advprog.eshop.enums.OrderStatus; +import id.ac.ui.cs.advprog.eshop.model.Order; +import id.ac.ui.cs.advprog.eshop.model.Product; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class OrderRepositoryTest { + OrderRepository orderRepository; + List orders; + + @BeforeEach + void setUp() { + orderRepository = new OrderRepository(); + + List products = new ArrayList<>(); + Product product1 = new Product(); + product1.setProductId("eb558e9f-1c39-460e-8860-71af6af63bd6"); + product1.setProductName("Sampo Cap Bambang"); + product1.setProductQuantity(2); + products.add(product1); + + orders = new ArrayList<>(); + Order order1 = new Order("13652556-012a-4c07-b546-54eb1396d79b", products, 1708560000L, "Safira Sudrajat"); + orders.add(order1); + Order order2 = new Order("7f9e15bb-4b15-42f4-aebc-c3af385fb878", products, 1708570000L, "Safira Sudrajat"); + orders.add(order2); + Order order3 = new Order("e334ef48-9eff-4da8-9487-8ee697ecbf1e", products, 1708570000L, "Bambang Sudrajat"); + orders.add(order3); + } + + @Test + void testSaveCreate() { + Order order = orders.get(1); + Order result = orderRepository.save(order); + + Order findResult = orderRepository.findById(orders.get(1).getId()); + assertEquals(order.getId(), result.getId()); + assertEquals(order.getId(), findResult.getId()); + assertEquals(order.getOrderTime(), findResult.getOrderTime()); + assertEquals(order.getAuthor(), findResult.getAuthor()); + assertEquals(order.getStatus(), findResult.getStatus()); + } + + + @Test + void testSaveUpdate() { + Order order = orders.get(1); + orderRepository.save(order); + Order newOrder = new Order(order.getId(), order.getProducts(), order.getOrderTime(), order.getAuthor(), OrderStatus.SUCCESS.getValue()); + Order result = orderRepository.save(newOrder); + + Order findResult = orderRepository.findById(orders.get(1).getId()); + assertEquals(order.getId(), result.getId()); + assertEquals(order.getId(), findResult.getId()); + assertEquals(order.getOrderTime(), findResult.getOrderTime()); + assertEquals(order.getAuthor(), findResult.getAuthor()); + assertEquals(OrderStatus.SUCCESS.getValue(), findResult.getStatus()); + } + @Test + void testFindByIdIfIdFound() { + for (Order order : orders) { + orderRepository.save(order); + } + + Order findResult = orderRepository.findById(orders.get(1).getId()); + assertEquals(orders.get(1).getId(), findResult.getId()); + assertEquals(orders.get(1).getOrderTime(), findResult.getOrderTime()); + assertEquals(orders.get(1).getAuthor(), findResult.getAuthor()); + assertEquals(orders.get(1).getStatus(), findResult.getStatus()); + } + + @Test + void testFindByIdIfIdNotFound() { + for (Order order : orders) { + orderRepository.save(order); + } + + Order findResult = orderRepository.findById("zczc"); + assertNull(findResult); + } + + @Test + void testFindAllByAuthorIfAuthorCorrect(){ + for (Order order : orders){ + orderRepository.save(order); + } + + List orderList = orderRepository.findAllByAuthor( + orders.get(1).getAuthor()); + assertEquals(2, orderList.size()); + } + + @Test + void testFindAllBuAuthorIfAllLowercase(){ + orderRepository.save(orders.get(1)); + + List orderList = orderRepository.findAllByAuthor( + orders.get(1).getAuthor().toLowerCase()); + assertTrue(orderList.isEmpty()); + } +} diff --git a/src/test/java/id/ac/ui/cs/advprog/eshop/repository/PaymentRepositoryTest.java b/src/test/java/id/ac/ui/cs/advprog/eshop/repository/PaymentRepositoryTest.java new file mode 100644 index 0000000..0cdc8c3 --- /dev/null +++ b/src/test/java/id/ac/ui/cs/advprog/eshop/repository/PaymentRepositoryTest.java @@ -0,0 +1,123 @@ +package id.ac.ui.cs.advprog.eshop.repository; + + +import id.ac.ui.cs.advprog.eshop.model.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +class PaymentRepositoryTest { + PaymentRepository paymentRepository; + List payments; + + @BeforeEach + void setUp() { + paymentRepository = new PaymentRepository(); + + // Make products + List products = new ArrayList<>(); + Product product1 = new Product(); + product1.setProductId("eb558e9f-1c39-460e-8860-71af6af63bd6"); + product1.setProductName("Sampo Cap Bambang"); + product1.setProductQuantity(2); + products.add(product1); + + // Make orders + List orders = new ArrayList<>(); + Order order1 = new Order("13652556-012a-4c07-b546-54eb1396d79b", products, 1708560000L, "Safira Sudrajat"); + orders.add(order1); + Order order2 = new Order("7f9e15bb-4b15-42f4-aebc-c3af385fb878", products, 1708570000L, "Safira Sudrajat"); + orders.add(order2); + Order order3 = new Order("e334ef48-9eff-4da8-9487-8ee697ecbf1e", products, 1708570000L, "Bambang Sudrajat"); + orders.add(order3); + + // Make payments + payments = new ArrayList<>(); + + Map paymentData1 = new HashMap(); + paymentData1.put("voucherCode", "ESHOP1234ABC5678"); + Payment payment1 = new PaymentVoucherCode("6c93d3e2-b009-46ba-9d15-f03d85adc2de", orders.getFirst(), paymentData1); + payments.add(payment1); + + Map paymentData2 = new HashMap(); + paymentData2.put("address", "Jalan Anggur"); + paymentData2.put("deliveryFee", "12000"); + Payment payment2 = new PaymentCashOnDelivery("6c93d3e2-b009-46ba-9d15-f03d85adc2d2", orders.getFirst(), paymentData2); + payments.add(payment2); + } + + + @Test + void testSaveCreate() { + Payment payment = payments.get(1); + Payment result = paymentRepository.save(payment); + + Payment findResult = paymentRepository.findById(payments.get(1).getId()); + + assertEquals(payment.getId(), result.getId()); + assertEquals(payment.getId(), findResult.getId()); + assertEquals(payment.getStatus(), findResult.getStatus()); + assertEquals(payment.getPaymentData(), findResult.getPaymentData()); + assertSame(payment.getOrder(), findResult.getOrder()); + } + + + @Test + void testSaveUpdate() { + // create new payment + Payment payment = payments.get(1); + paymentRepository.save(payment); + + // change payment data + Payment newPayment = new PaymentCashOnDelivery(payment.getId(), payment.getOrder(), payments.get(0).getPaymentData()); + Payment result = paymentRepository.save(newPayment); + + Payment findResult = paymentRepository.findById(payments.get(1).getId()); + + assertEquals(payment.getId(), result.getId()); + assertEquals(payment.getId(), findResult.getId()); + assertEquals(payments.getFirst().getPaymentData(), findResult.getPaymentData()); + assertSame(payment.getOrder(), findResult.getOrder()); + + + } + @Test + void testFindByIdIfIdFound() { + for (Payment payment : payments) { + paymentRepository.save(payment); + } + + Payment findResult = paymentRepository.findById(payments.get(1).getId()); + + assertEquals(payments.get(1).getId(), findResult.getId()); + assertEquals(payments.get(1).getStatus(), findResult.getStatus()); + assertEquals(payments.get(1).getPaymentData(), findResult.getPaymentData()); + assertSame(payments.get(1).getOrder(), findResult.getOrder()); + } + + @Test + void testFindByIdIfIdNotFound() { + for (Payment payment: payments) { + paymentRepository.save(payment); + } + + Payment findResult = paymentRepository.findById("zczc"); + assertNull(findResult); + } + + @Test + void testFindAll(){ + for (Payment payment: payments) { + paymentRepository.save(payment); + } + + List paymentList = paymentRepository.getAllPayment(); + assertEquals(2, paymentList.size()); + } +} diff --git a/src/test/java/id/ac/ui/cs/advprog/eshop/service/OrderServiceImplTest.java b/src/test/java/id/ac/ui/cs/advprog/eshop/service/OrderServiceImplTest.java new file mode 100644 index 0000000..2f209de --- /dev/null +++ b/src/test/java/id/ac/ui/cs/advprog/eshop/service/OrderServiceImplTest.java @@ -0,0 +1,140 @@ +package id.ac.ui.cs.advprog.eshop.service; + + +import id.ac.ui.cs.advprog.eshop.enums.OrderStatus; +import id.ac.ui.cs.advprog.eshop.model.Order; +import id.ac.ui.cs.advprog.eshop.model.Product; +import id.ac.ui.cs.advprog.eshop.repository.OrderRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class OrderServiceImplTest { + @InjectMocks + OrderServiceImpl orderService; + @Mock + OrderRepository orderRepository; + List orders; + + @BeforeEach + void setUp() { + List products = new ArrayList<>(); + Product product1 = new Product(); + product1.setProductId("eb558e9f-1c39-460e-8860-71af6af63bd6"); + product1.setProductName("Sampo Cap Bambang"); + product1.setProductQuantity(2); + products.add(product1); + orders = new ArrayList<>(); + Order order1 = new Order("13652556-012a-4c07-b546-54eb1396d79b", products, 1708560000L, "Safira Sudrajat"); + orders.add(order1); + Order order2 = new Order("7f9e15bb-4b15-42f4-aebc-c3af385fb078", products, 1708570000L, "Safira Sudrajat"); + orders.add(order2); + } + + + @Test + void testCreateOrder() { + Order order = orders.get(1); + doReturn(order).when(orderRepository).save(order); + + Order result = orderService.createOrder(order); + verify(orderRepository, times(1)).save(order); + assertEquals(order.getId(), result.getId()); + } + + @Test + void testCreateOrderIfAlreadyExists() { + Order order = orders.get(1); + doReturn(order).when(orderRepository).findById(order.getId()); + + assertNull(orderService.createOrder(order)); + verify(orderRepository, times(0)).save(order); + } + + @Test + void testUpdateStatus() { + Order order = orders.get(1); + Order newOrder = new Order(order.getId(), order.getProducts(), order.getOrderTime(), + order.getAuthor(), OrderStatus.SUCCESS.getValue()); + doReturn(order).when(orderRepository).findById(order.getId()); + doReturn(newOrder).when(orderRepository).save(any(Order.class)); + + Order result = orderService.updateStatus(order.getId(), OrderStatus.SUCCESS.getValue()); + + assertEquals(order.getId(), result.getId()); + assertEquals(OrderStatus.SUCCESS.getValue(), result.getStatus()); + verify(orderRepository, times(1)).save(any(Order.class)); + } + + + @Test + void testUpdateStatusInvalidStatus() { + Order order = orders.get(1); + doReturn(order).when(orderRepository).findById(order.getId()); + + assertThrows(IllegalArgumentException.class, + () -> orderService.updateStatus(order.getId(), "MEOW")); + + verify(orderRepository, times(0)).save(any(Order.class)); + } + + + @Test + void testUpdateStatusInvalidOrderId() { + doReturn(null).when(orderRepository).findById("zczc"); + + assertThrows(NoSuchElementException.class, + () -> orderService.updateStatus("zczc", OrderStatus.SUCCESS.getValue())); + + verify(orderRepository, times(0)).save(any(Order.class)); + } + + @Test + void testFindByIdIfIdFound() { + Order order = orders.get(1); + doReturn(order).when(orderRepository).findById(order.getId()); + + Order result = orderService.findById(order.getId()); + assertEquals(order.getId(), result.getId()); + } + + @Test + void testFindByIdIfIdNotFound() { + doReturn(null).when(orderRepository).findById("zczc"); + assertNull(orderService.findById("zczc")); + } + + @Test + void testFindAllByAuthorIfAuthorCorrect() { + Order order = orders.get(1); + doReturn(orders).when(orderRepository).findAllByAuthor(order.getAuthor()); + + List results = orderService.findAllByAuthor(order.getAuthor()); + for (Order result : results){ + assertEquals(order.getAuthor(), result.getAuthor()); + } + assertEquals(2, results.size()); + } + + + @Test + void testFindAllByAuthorIfAllLowercase() { + Order order = orders.get(1); + doReturn(new ArrayList()).when(orderRepository) + .findAllByAuthor(order.getAuthor().toLowerCase()); + + List results = orderService.findAllByAuthor(order.getAuthor().toLowerCase()); + assertTrue(results.isEmpty()); + } +} diff --git a/src/test/java/id/ac/ui/cs/advprog/eshop/service/PaymentServiceImplTest.java b/src/test/java/id/ac/ui/cs/advprog/eshop/service/PaymentServiceImplTest.java new file mode 100644 index 0000000..03de056 --- /dev/null +++ b/src/test/java/id/ac/ui/cs/advprog/eshop/service/PaymentServiceImplTest.java @@ -0,0 +1,173 @@ +package id.ac.ui.cs.advprog.eshop.service; + + +import id.ac.ui.cs.advprog.eshop.enums.PaymentStatus; +import id.ac.ui.cs.advprog.eshop.model.*; +import id.ac.ui.cs.advprog.eshop.repository.PaymentRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class PaymentServiceImplTest { + @InjectMocks + PaymentServiceImpl paymentService; + @Mock + PaymentRepository paymentRepository; + List> paymentDatas; + List orders; + + @BeforeEach + void setUp() { + + // Make product + List products = new ArrayList<>(); + Product product1 = new Product(); + product1.setProductId("eb558e9f-1c39-460e-8860-71af6af63bd6"); + product1.setProductName("Sampo Cap Bambang"); + product1.setProductQuantity(2); + products.add(product1); + + // Make order + orders = new ArrayList<>(); + Order order1 = new Order("13652556-012a-4c07-b546-54eb1396d79b", products, 1708560000L, "Safira Sudrajat"); + orders.add(order1); + Order order2 = new Order("7f9e15bb-4b15-42f4-aebc-c3af385fb078", products, 1708570000L, "Safira Sudrajat"); + orders.add(order2); + + + // Make payment datas + paymentDatas = new ArrayList<>(); + + Map paymentData1 = new HashMap(); + paymentData1.put("voucherCode", "ESHOP1234ABC5678"); + paymentDatas.add(paymentData1); + + Map paymentData2 = new HashMap(); + paymentData2.put("address", "Jalan Anggur"); + paymentData2.put("deliveryFee", "12000"); + paymentDatas.add(paymentData2); + } + + @Test + void testCreatePaymentVoucherCode() { + String id = "75c64e96-d4d7-454b-8ee5-7086efff516c"; + Payment payment = new PaymentVoucherCode(id, orders.get(1), paymentDatas.get(0)); + + doReturn(null).when(paymentRepository).findById(id); + doReturn(payment).when(paymentRepository).save(any(Payment.class)); + + Payment result = paymentService.addPayment(id, orders.get(1), "VOUCHER_CODE", paymentDatas.get(0)); + + verify(paymentRepository, times(1)).save(any(Payment.class)); + assertEquals(payment.getId(), result.getId()); + } + + @Test + void testInvalidPaymentMethod() { + String id = "75c64e96-d4d7-454b-8ee5-7086efff516c"; + Payment payment = new PaymentVoucherCode(id, orders.get(1), paymentDatas.get(0)); + + doReturn(null).when(paymentRepository).findById(id); + assertThrows(IllegalArgumentException.class, + () -> paymentService.addPayment(id, orders.get(1), "WKWKWKWK", paymentDatas.get(0))); + + verify(paymentRepository, times(0)).save(payment); + } + + + @Test + void testCreatePaymentIfAlreadyExists() { + String id = "75c64e96-d4d7-454b-8ee5-7086efff516c"; + Payment payment = new PaymentVoucherCode(id, orders.get(1), paymentDatas.get(0)); + + doReturn(payment).when(paymentRepository).findById(payment.getId()); + + assertNull(paymentService.addPayment(id, orders.get(1), "VOUCHER_CODE", paymentDatas.get(0))); + verify(paymentRepository, times(0)).save(payment); + } + + @Test + void testSetStatus() { + Payment payment = new PaymentCashOnDelivery("75c64e96-d4d7-454b-8ee5-7086efff516c", orders.get(1), paymentDatas.get(0)); + assertEquals(PaymentStatus.REJECTED.getValue(), payment.getStatus()); + + Payment newPayment = new PaymentVoucherCode(payment.getId(), payment.getOrder(), paymentDatas.get(1)); + + + doReturn(payment).when(paymentRepository).findById(payment.getId()); + doReturn(newPayment).when(paymentRepository).save(any(Payment.class)); + + Payment result = paymentService.setStatus(payment, PaymentStatus.SUCCESS.getValue()); + + assertEquals(payment.getId(), result.getId()); + assertEquals(PaymentStatus.SUCCESS.getValue(), result.getStatus()); + verify(paymentRepository, times(1)).save(any(Payment.class)); + } + + + @Test + void testSetStatusInvalidStatus() { + Payment payment = new PaymentCashOnDelivery("75c64e96-d4d7-454b-8ee5-7086efff516c", orders.get(1), paymentDatas.get(0)); + assertEquals(PaymentStatus.REJECTED.getValue(), payment.getStatus()); + + doReturn(payment).when(paymentRepository).findById(payment.getId()); + + assertThrows(IllegalArgumentException.class, + () -> paymentService.setStatus(payment, "MEOW")); + + verify(paymentRepository, times(0)).save(any(Payment.class)); + } + + + @Test + void testSetStatusInvalidPaymentId() { + Payment payment = new PaymentCashOnDelivery("75c64e96-d4d7-454b-8ee5-7086efff516c", orders.get(1), paymentDatas.get(0)); + + doReturn(null).when(paymentRepository).findById(payment.getId()); + + assertThrows(NoSuchElementException.class, + () -> paymentService.setStatus(payment, PaymentStatus.SUCCESS.getValue())); + + verify(paymentRepository, times(0)).save(any(Payment.class)); + } + + @Test + void testGetPaymentIfIdFound() { + Payment payment = new PaymentCashOnDelivery("75c64e96-d4d7-454b-8ee5-7086efff516c", orders.get(1), paymentDatas.get(0)); + + doReturn(payment).when(paymentRepository).findById(payment.getId()); + + Payment result = paymentService.getPayment(payment.getId()); + assertEquals(payment.getId(), result.getId()); + } + + @Test + void testGetPaymentIfIfIdNotFound() { + Payment payment = new PaymentCashOnDelivery("75c64e96-d4d7-454b-8ee5-7086efff516c", orders.get(1), paymentDatas.get(0)); + + assertNull(paymentService.getPayment(payment.getId())); + } + + @Test + void testGetAllPayments() { + Payment payment = new PaymentCashOnDelivery("75c64e96-d4d7-454b-8ee5-7086efff516c", orders.get(1), paymentDatas.get(0)); + List payments = new ArrayList<>(); + payments.add(payment); + + doReturn(payments).when(paymentRepository).getAllPayment(); + + List results = paymentService.getAllPayments(); + assertEquals(payments, results); + + assertEquals(1, results.size()); + } +}