Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: #37
This commit was merged in pull request #37.
This commit is contained in:
@@ -45,4 +45,16 @@ public class EateryEntity extends BaseEntity {
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public static EateryEntity findByOwnerId(String ownerId) {
|
||||
UUID ownerUUID = UUID.fromString(ownerId);
|
||||
|
||||
return EateryEntity.find("ownerId", ownerUUID).firstResult();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public static EateryEntity findByOwnerId(UUID ownerId) {
|
||||
return EateryEntity.find("ownerId", ownerId).firstResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package com.drinkool.entities;
|
||||
|
||||
import com.drinkool.lib.entities.BaseEntity;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
@Entity
|
||||
@Table
|
||||
public class EateryInventoryItemEntity extends BaseEntity {
|
||||
|
||||
public double quantity;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "inventory_item_id")
|
||||
public InventoryItemEntity inventoryItem;
|
||||
|
||||
private EateryInventoryItemEntity() {}
|
||||
|
||||
// Create
|
||||
@Transactional
|
||||
public static EateryInventoryItemEntity create(
|
||||
String name,
|
||||
double quantity,
|
||||
String unit
|
||||
) {
|
||||
String itemName = name.toLowerCase();
|
||||
|
||||
InventoryItemEntity item = InventoryItemEntity.find(
|
||||
"name",
|
||||
itemName
|
||||
).firstResult();
|
||||
|
||||
if (item == null || item.unit != unit) {
|
||||
if (unit != null || unit == "") {
|
||||
item = InventoryItemEntity.create(itemName, unit);
|
||||
} else {
|
||||
item = InventoryItemEntity.create(itemName);
|
||||
}
|
||||
}
|
||||
|
||||
EateryInventoryItemEntity eateryInventoryItem =
|
||||
new EateryInventoryItemEntity();
|
||||
|
||||
eateryInventoryItem.quantity = quantity;
|
||||
eateryInventoryItem.inventoryItem = item;
|
||||
|
||||
eateryInventoryItem.persist();
|
||||
|
||||
return eateryInventoryItem;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.drinkool.entities;
|
||||
|
||||
import com.drinkool.lib.entities.BaseEntity;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
@Entity
|
||||
@Table(name = "inventory_items")
|
||||
public class InventoryItemEntity extends BaseEntity {
|
||||
|
||||
public String name;
|
||||
public String unit;
|
||||
|
||||
private InventoryItemEntity() {}
|
||||
|
||||
// Create
|
||||
@Transactional
|
||||
public static InventoryItemEntity create(String name, String unit) {
|
||||
InventoryItemEntity item = new InventoryItemEntity();
|
||||
|
||||
item.name = name;
|
||||
item.unit = unit;
|
||||
|
||||
item.persist();
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public static InventoryItemEntity create(String name) {
|
||||
return InventoryItemEntity.create(name, "unit");
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package com.drinkool.entities;
|
||||
import com.drinkool.lib.entities.BaseEntity;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.*;
|
||||
|
||||
@Entity
|
||||
@Table
|
||||
@@ -19,45 +18,19 @@ public class MenuItemEntity extends BaseEntity {
|
||||
@JoinColumn(name = "eatery_id")
|
||||
public EateryEntity eatery;
|
||||
|
||||
// Danh sách các nguyên liệu cấu thành món ăn này
|
||||
@OneToMany(
|
||||
mappedBy = "menuItem",
|
||||
cascade = CascadeType.ALL,
|
||||
orphanRemoval = true
|
||||
)
|
||||
public List<MenuItemIngredientEntity> ingredients = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Thêm nguyên liệu vào món ăn với định lượng cụ thể
|
||||
*/
|
||||
@Transactional
|
||||
public void addIngredient(
|
||||
EateryInventoryItemEntity inventoryItem,
|
||||
double requiredQty
|
||||
) {
|
||||
MenuItemIngredientEntity ingredient = MenuItemIngredientEntity.create(
|
||||
this,
|
||||
inventoryItem,
|
||||
requiredQty
|
||||
);
|
||||
|
||||
this.ingredients.add(ingredient);
|
||||
|
||||
this.persist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Phương thức tiện ích để tạo nhanh Menu Item từ tên
|
||||
*/
|
||||
@Transactional
|
||||
public static MenuItemEntity create(String name, double price) {
|
||||
MenuItemEntity menu = new MenuItemEntity();
|
||||
public static MenuItemEntity create(EateryEntity eatery, String name, double price) {
|
||||
MenuItemEntity menuItem = new MenuItemEntity();
|
||||
|
||||
menu.name = name;
|
||||
menu.price = price;
|
||||
menuItem.name = name;
|
||||
menuItem.price = price;
|
||||
menuItem.eatery = eatery;
|
||||
|
||||
menu.persist();
|
||||
menuItem.persist();
|
||||
|
||||
return menu;
|
||||
return menuItem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.drinkool.entities;
|
||||
|
||||
import com.drinkool.lib.entities.BaseEntity;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "menu_item_ingredients")
|
||||
public class MenuItemIngredientEntity extends BaseEntity {
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "menu_item_id")
|
||||
public MenuItemEntity menuItem;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "inventory_item_id")
|
||||
public EateryInventoryItemEntity inventoryItem;
|
||||
|
||||
public double requiredQuantity;
|
||||
|
||||
private MenuItemIngredientEntity() {}
|
||||
|
||||
public static MenuItemIngredientEntity create(
|
||||
MenuItemEntity menuItem,
|
||||
EateryInventoryItemEntity inventoryItem,
|
||||
double requiredQuantity
|
||||
) {
|
||||
MenuItemIngredientEntity ingredient = new MenuItemIngredientEntity();
|
||||
|
||||
ingredient.menuItem = menuItem;
|
||||
ingredient.inventoryItem = inventoryItem;
|
||||
ingredient.requiredQuantity = requiredQuantity;
|
||||
|
||||
ingredient.persist();
|
||||
|
||||
return ingredient;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,19 @@
|
||||
package com.drinkool.services;
|
||||
|
||||
import com.drinkool.InternalValue;
|
||||
import com.drinkool.Role;
|
||||
import com.drinkool.dtos.event.ManagerCreate;
|
||||
import com.drinkool.entities.EateryEntity;
|
||||
import com.drinkool.entities.MenuItemEntity;
|
||||
import io.vertx.core.http.HttpServerRequest;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.eclipse.microprofile.graphql.GraphQLApi;
|
||||
import org.eclipse.microprofile.graphql.Mutation;
|
||||
import org.eclipse.microprofile.graphql.Name;
|
||||
import org.eclipse.microprofile.graphql.Query;
|
||||
import org.eclipse.microprofile.reactive.messaging.Incoming;
|
||||
@@ -15,6 +22,9 @@ import org.eclipse.microprofile.reactive.messaging.Incoming;
|
||||
@GraphQLApi
|
||||
public class EateryService {
|
||||
|
||||
@Inject
|
||||
HttpServerRequest request;
|
||||
|
||||
@Incoming("manager-in")
|
||||
@Transactional
|
||||
public void consumeManagerSignup(ManagerCreate input) {
|
||||
@@ -32,4 +42,32 @@ public class EateryService {
|
||||
public EateryEntity getEatery(@Name("id") UUID id) {
|
||||
return EateryEntity.findById(id);
|
||||
}
|
||||
|
||||
@Mutation("addMenuItem")
|
||||
@RolesAllowed(Role.Manager)
|
||||
@Transactional
|
||||
public MenuItemEntity addMenuItem(
|
||||
@Name("name") String name,
|
||||
@Name("price") double price
|
||||
) {
|
||||
String ownerId = request.getHeader(InternalValue.userId);
|
||||
|
||||
EateryEntity eatery = EateryEntity.findByOwnerId(ownerId);
|
||||
if (eatery == null) return null;
|
||||
|
||||
MenuItemEntity item = MenuItemEntity.create(eatery, name, price);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
@Query("menuItemsByEatery")
|
||||
public List<MenuItemEntity> getMenuItemsByEatery(
|
||||
@Name("eateryId") UUID eateryId
|
||||
) {
|
||||
EateryEntity eatery = EateryEntity.findById(eateryId);
|
||||
|
||||
if (eatery == null) return List.of();
|
||||
|
||||
return MenuItemEntity.list("eatery", eatery);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.drinkool.services;
|
||||
|
||||
import com.drinkool.dtos.AddInventory;
|
||||
import com.drinkool.entities.InventoryItemEntity;
|
||||
import jakarta.transaction.Transactional;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Path("/api/inventory")
|
||||
public class InventoryService {
|
||||
|
||||
@POST
|
||||
@Path("/create")
|
||||
@Transactional
|
||||
public Response create(AddInventory input) {
|
||||
InventoryItemEntity.create(input.name, input.unit);
|
||||
|
||||
return Response.ok().build();
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package com.drinkool.entities;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@QuarkusTest
|
||||
public class EateryInventoryItemEntityTest {
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testAdd_WhenItemExists_ShouldUseExistingItem() {
|
||||
String itemName = "Coca Cola";
|
||||
int quantity = 10;
|
||||
|
||||
InventoryItemEntity.create(itemName);
|
||||
|
||||
EateryInventoryItemEntity eateryItem = EateryInventoryItemEntity.create(
|
||||
itemName,
|
||||
quantity,
|
||||
""
|
||||
);
|
||||
|
||||
EateryInventoryItemEntity savedEntity = EateryInventoryItemEntity.find(
|
||||
"id",
|
||||
eateryItem.id
|
||||
).firstResult();
|
||||
assertNotNull(savedEntity);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testAdd_WhenItemDoesNotExist_ShouldCreateNewItem() {
|
||||
String itemName = "Pepsi";
|
||||
int quantity = 5;
|
||||
String unit = "Bottle";
|
||||
|
||||
EateryInventoryItemEntity eateryItem = EateryInventoryItemEntity.create(
|
||||
itemName,
|
||||
quantity,
|
||||
unit
|
||||
);
|
||||
|
||||
EateryInventoryItemEntity savedEntity = EateryInventoryItemEntity.find(
|
||||
"id",
|
||||
eateryItem.id
|
||||
).firstResult();
|
||||
assertNotNull(savedEntity);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package com.drinkool.entities;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@QuarkusTest
|
||||
public class InventoryItemEntityTest {
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateInventoryItem() {
|
||||
// 1. Chuẩn bị dữ liệu (Lưu ý: Không còn biến quantity nữa)
|
||||
String name = "Trà sữa truyền thống";
|
||||
String unit = "Ly";
|
||||
|
||||
// 2. Gọi hàm static create (Không dùng new hay hàm add nữa)
|
||||
// Hàm này vừa tạo object, vừa gán data, vừa gọi persist() luôn
|
||||
InventoryItemEntity item = InventoryItemEntity.create(name, unit);
|
||||
|
||||
// 3. Kiểm chứng
|
||||
Assertions.assertNotNull(item, "Entity tạo ra không được null");
|
||||
Assertions.assertEquals(name, item.name, "Tên không khớp");
|
||||
Assertions.assertEquals(unit, item.unit, "Đơn vị không khớp");
|
||||
Assertions.assertNotNull(
|
||||
item.id,
|
||||
"ID phải được sinh ra tự động sau khi persist"
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateWithDefaultUnit() {
|
||||
// 1. Chuẩn bị dữ liệu
|
||||
String name = "Trân châu đen";
|
||||
|
||||
// 2. Gọi hàm static create rút gọn (chỉ truyền name, unit sẽ tự là "unit")
|
||||
InventoryItemEntity item = InventoryItemEntity.create(name);
|
||||
|
||||
// 3. Kiểm chứng
|
||||
Assertions.assertNotNull(item, "Entity tạo ra không được null");
|
||||
Assertions.assertEquals(name, item.name, "Tên không khớp");
|
||||
Assertions.assertEquals("unit", item.unit, "Unit mặc định phải là 'unit'");
|
||||
Assertions.assertNotNull(
|
||||
item.id,
|
||||
"ID phải được sinh ra tự động sau khi persist"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
package com.drinkool.entities;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@QuarkusTest
|
||||
public class MenuItemEntityTest {
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateMenuItemSuccessfully() {
|
||||
// 1. Chuẩn bị dữ liệu (Arrange)
|
||||
String name = "Cà phê sữa đá";
|
||||
double price = 29000.0;
|
||||
|
||||
// 2. Thực thi (Act) - Gọi hàm tĩnh create
|
||||
MenuItemEntity menuItem = MenuItemEntity.create(name, price);
|
||||
|
||||
// 3. Kiểm chứng (Assert)
|
||||
assertNotNull(menuItem, "Thực thể MenuItem không được null");
|
||||
assertEquals(name, menuItem.name, "Tên món ăn không khớp");
|
||||
assertEquals(price, menuItem.price, "Giá món ăn không khớp");
|
||||
assertNotNull(menuItem.id, "ID phải được tự động sinh ra sau khi persist");
|
||||
assertTrue(
|
||||
menuItem.ingredients.isEmpty(),
|
||||
"Danh sách nguyên liệu ban đầu phải rỗng"
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testAddIngredientSuccessfully() {
|
||||
// 1. Chuẩn bị dữ liệu (Arrange)
|
||||
// Tạo món ăn
|
||||
MenuItemEntity menuItem = MenuItemEntity.create(
|
||||
"Trà sữa trân châu",
|
||||
45000.0
|
||||
);
|
||||
|
||||
// Tạo nguyên liệu trong kho (Dùng đúng hàm add() của EateryInventoryItemEntity như đã fix)
|
||||
EateryInventoryItemEntity inventoryItem = EateryInventoryItemEntity.create(
|
||||
"Trân châu đen",
|
||||
50,
|
||||
"kg"
|
||||
);
|
||||
|
||||
double requiredQty = 0.2; // Cần 0.2 kg trân châu cho 1 ly
|
||||
|
||||
// 2. Thực thi (Act) - Thêm nguyên liệu vào món ăn
|
||||
menuItem.addIngredient(inventoryItem, requiredQty);
|
||||
|
||||
// 3. Kiểm chứng (Assert)
|
||||
// Kiểm tra danh sách nguyên liệu của món ăn
|
||||
assertFalse(
|
||||
menuItem.ingredients.isEmpty(),
|
||||
"Danh sách nguyên liệu không được rỗng sau khi thêm"
|
||||
);
|
||||
assertEquals(
|
||||
1,
|
||||
menuItem.ingredients.size(),
|
||||
"Phải có đúng 1 nguyên liệu trong danh sách"
|
||||
);
|
||||
|
||||
// Lấy phần tử nguyên liệu đầu tiên ra để kiểm tra chi tiết các liên kết
|
||||
MenuItemIngredientEntity addedIngredient = menuItem.ingredients.get(0);
|
||||
|
||||
assertNotNull(
|
||||
addedIngredient.id,
|
||||
"ID của Entity trung gian phải được sinh ra"
|
||||
);
|
||||
assertEquals(
|
||||
menuItem.id,
|
||||
addedIngredient.menuItem.id,
|
||||
"Khóa ngoại MenuItem bị sai"
|
||||
);
|
||||
assertEquals(
|
||||
inventoryItem.id,
|
||||
addedIngredient.inventoryItem.id,
|
||||
"Khóa ngoại InventoryItem bị sai"
|
||||
);
|
||||
assertEquals(
|
||||
requiredQty,
|
||||
addedIngredient.requiredQuantity,
|
||||
"Định lượng (requiredQty) không khớp"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package com.drinkool.entities;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@QuarkusTest
|
||||
public class MenuItemIngredientEntityTest {
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testCreate_ShouldPersistIngredientSuccessfully() {
|
||||
// 1. Chuẩn bị dữ liệu giả định
|
||||
|
||||
String menuItemName = "Milk Tea";
|
||||
double menuItemPrice = 40;
|
||||
|
||||
MenuItemEntity menuItem = MenuItemEntity.create(
|
||||
menuItemName,
|
||||
menuItemPrice
|
||||
);
|
||||
|
||||
String inventoryItemName = "Water";
|
||||
int inventoryItemQuantity = 10; // Đổi thành int cho khớp với kiểu của EateryInventoryItemEntity
|
||||
String inventoryItemUnit = "l";
|
||||
|
||||
// SỬA Ở ĐÂY: Khởi tạo bằng new và dùng hàm add() đúng như cấu trúc class của bạn
|
||||
EateryInventoryItemEntity inventoryItem = EateryInventoryItemEntity.create(
|
||||
inventoryItemName,
|
||||
inventoryItemQuantity,
|
||||
inventoryItemUnit
|
||||
);
|
||||
// Lưu ý: Hàm add() của bạn đã có sẵn lệnh this.persist() bên trong nên không cần gọi lại nữa!
|
||||
|
||||
double requiredQuantity = 0.5;
|
||||
|
||||
// 2. Gọi hàm static create cần test
|
||||
MenuItemIngredientEntity createdIngredient =
|
||||
MenuItemIngredientEntity.create(
|
||||
menuItem,
|
||||
inventoryItem,
|
||||
requiredQuantity
|
||||
);
|
||||
|
||||
// 3. Kiểm tra kết quả
|
||||
assertNotNull(createdIngredient.id, "ID không được null sau khi persist");
|
||||
|
||||
// Truy vấn lại từ Database để đảm bảo dữ liệu đã được lưu đúng
|
||||
MenuItemIngredientEntity savedEntity = MenuItemIngredientEntity.findById(
|
||||
createdIngredient.id
|
||||
);
|
||||
|
||||
assertNotNull(savedEntity);
|
||||
assertEquals(menuItem.id, savedEntity.menuItem.id);
|
||||
assertEquals(inventoryItem.id, savedEntity.inventoryItem.id);
|
||||
assertEquals(requiredQuantity, savedEntity.requiredQuantity);
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,16 @@ package com.drinkool.services;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.hasItems;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
|
||||
import com.drinkool.InternalValue;
|
||||
import com.drinkool.Role;
|
||||
import com.drinkool.dtos.event.ManagerCreate;
|
||||
import com.drinkool.entities.EateryEntity;
|
||||
import com.drinkool.entities.MenuItemEntity;
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import io.restassured.http.ContentType;
|
||||
import io.smallrye.reactive.messaging.memory.InMemoryConnector;
|
||||
@@ -54,21 +59,32 @@ public class EateryServiceTest {
|
||||
|
||||
private UUID lastSavedId;
|
||||
private String lastSavedName;
|
||||
private UUID lastOwnerId = UUID.randomUUID();
|
||||
|
||||
@BeforeEach
|
||||
@Transactional
|
||||
void setup() {
|
||||
MenuItemEntity.deleteAll();
|
||||
EateryEntity.deleteAll();
|
||||
|
||||
lastSavedName = faker.restaurant().name();
|
||||
|
||||
EateryEntity eatery = new EateryEntity();
|
||||
lastSavedId = eatery.create(UUID.randomUUID(), lastSavedName).id;
|
||||
eatery = eatery.create(lastOwnerId, lastSavedName);
|
||||
lastSavedId = eatery.id;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
EateryEntity e = new EateryEntity();
|
||||
e.create(UUID.randomUUID(), faker.restaurant().name());
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
MenuItemEntity.create(
|
||||
eatery,
|
||||
faker.food().dish(),
|
||||
faker.number().randomDouble(2, 10, 100)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -106,4 +122,144 @@ public class EateryServiceTest {
|
||||
.statusCode(200)
|
||||
.body("data.eateryById.name", is(lastSavedName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddMenuItemSuccess() {
|
||||
String mutation =
|
||||
"mutation addMenuItem($name: String!, $price: Float!) {" +
|
||||
" addMenuItem(name: $name, price: $price) {" +
|
||||
" id" +
|
||||
" name" +
|
||||
" price" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
java.util.Map<String, Object> variables = new java.util.HashMap<>();
|
||||
variables.put("name", "Trà Sữa");
|
||||
variables.put("price", 30000.0);
|
||||
|
||||
java.util.Map<String, Object> requestBody = new java.util.HashMap<>();
|
||||
requestBody.put("query", mutation);
|
||||
requestBody.put("variables", variables);
|
||||
|
||||
given()
|
||||
.contentType(ContentType.JSON)
|
||||
.header(InternalValue.role, Role.Manager)
|
||||
.header(InternalValue.userId, lastOwnerId) // Thay "x-user-id" bằng InternalValue.userId của bạn
|
||||
.body(requestBody)
|
||||
.when()
|
||||
.post("/graphql")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body("data.addMenuItem.name", is("Trà Sữa"))
|
||||
.body("data.addMenuItem.id", notNullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddMenuItemFailInvalidRole() {
|
||||
String mutation =
|
||||
"mutation addMenuItem($name: String!, $price: Float!) {" +
|
||||
" addMenuItem(name: $name, price: $price) {" +
|
||||
" id" +
|
||||
" name" +
|
||||
" price" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
java.util.Map<String, Object> variables = new java.util.HashMap<>();
|
||||
variables.put("name", "Trà Sữa");
|
||||
variables.put("price", 30000.0);
|
||||
|
||||
java.util.Map<String, Object> requestBody = new java.util.HashMap<>();
|
||||
requestBody.put("query", mutation);
|
||||
requestBody.put("variables", variables);
|
||||
|
||||
given()
|
||||
.contentType(ContentType.JSON)
|
||||
.header(InternalValue.role, Role.Customer)
|
||||
.header(InternalValue.userId, lastOwnerId)
|
||||
.body(requestBody)
|
||||
.when()
|
||||
.post("/graphql")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body("data.addMenuItem.name", is("Trà Sữa"))
|
||||
.body("data.addMenuItem.id", notNullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddMenuItemFailInvalidOwner() {
|
||||
String mutation =
|
||||
"mutation { addMenuItem(name: \"Coffee\", price: 20000.0) { id } }";
|
||||
|
||||
java.util.Map<String, Object> requestBody = new java.util.HashMap<>();
|
||||
requestBody.put("query", mutation);
|
||||
|
||||
given()
|
||||
.contentType(ContentType.JSON)
|
||||
.header(InternalValue.role, Role.Manager)
|
||||
.header(InternalValue.userId, UUID.randomUUID())
|
||||
.body(requestBody)
|
||||
.when()
|
||||
.post("/graphql")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body("data.addMenuItem", is((Object) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMenuItemsByEatery_Success() {
|
||||
String query =
|
||||
"query getItems($id: String!) {" +
|
||||
" menuItemsByEatery(eateryId: $id) {" +
|
||||
" id" +
|
||||
" name" +
|
||||
" price" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
java.util.Map<String, Object> variables = new java.util.HashMap<>();
|
||||
variables.put("id", lastSavedId.toString());
|
||||
|
||||
java.util.Map<String, Object> requestBody = new java.util.HashMap<>();
|
||||
requestBody.put("query", query);
|
||||
requestBody.put("variables", variables);
|
||||
|
||||
given()
|
||||
.contentType(ContentType.JSON)
|
||||
.body(requestBody)
|
||||
.when()
|
||||
.post("/graphql")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body("data.menuItemsByEatery", hasSize(not(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMenuItemsByEatery_NotFound() {
|
||||
String randomId = UUID.randomUUID().toString();
|
||||
|
||||
String query =
|
||||
"query getItems($id: String!) {" +
|
||||
" menuItemsByEatery(eateryId: $id) {" +
|
||||
" id" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
java.util.Map<String, Object> variables = new java.util.HashMap<>();
|
||||
variables.put("id", randomId);
|
||||
|
||||
java.util.Map<String, Object> requestBody = new java.util.HashMap<>();
|
||||
requestBody.put("query", query);
|
||||
requestBody.put("variables", variables);
|
||||
|
||||
given()
|
||||
.contentType(ContentType.JSON)
|
||||
.body(requestBody)
|
||||
.when()
|
||||
.post("/graphql")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body("data.menuItemsByEatery", hasSize(0)); // Phải trả về List rỗng như code bạn viết
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.drinkool.services;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import com.drinkool.dtos.AddInventory;
|
||||
import com.drinkool.entities.InventoryItemEntity;
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import io.restassured.http.ContentType;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@QuarkusTest
|
||||
public class InventoryServiceTest {
|
||||
|
||||
@Test
|
||||
void add() {
|
||||
String name = UUID.randomUUID().toString();
|
||||
|
||||
AddInventory input = new AddInventory();
|
||||
input.name = name;
|
||||
|
||||
given()
|
||||
.contentType(ContentType.JSON)
|
||||
.body(input)
|
||||
.when()
|
||||
.post("/api/inventory/create")
|
||||
.then();
|
||||
|
||||
assertEquals(1, InventoryItemEntity.find("name", name).count());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.drinkool.controller;
|
||||
|
||||
import com.drinkool.dtos.GraphqlDto;
|
||||
import io.smallrye.graphql.client.GraphQLClient;
|
||||
import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient;
|
||||
import jakarta.ws.rs.POST;
|
||||
@@ -15,10 +16,11 @@ public class EateryController {
|
||||
|
||||
@POST
|
||||
@Path("/graphql")
|
||||
public Response forward(String query)
|
||||
public Response forward(GraphqlDto gqlRequest)
|
||||
throws ExecutionException, InterruptedException {
|
||||
io.smallrye.graphql.client.Response response = dynamicClient.executeSync(
|
||||
query
|
||||
gqlRequest.query,
|
||||
gqlRequest.variables
|
||||
);
|
||||
|
||||
if (response.hasError()) {
|
||||
|
||||
+16
-11
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,20 +21,25 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-security</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>2.15.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-kafka-client</artifactId>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-kafka-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.persistence</groupId>
|
||||
@@ -55,4 +60,4 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.drinkool.dtos;
|
||||
|
||||
public class GraphqlDto {
|
||||
|
||||
public String query;
|
||||
public java.util.Map<String, Object> variables;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.drinkool.lib.utils;
|
||||
|
||||
import com.drinkool.InternalValue;
|
||||
import io.quarkus.security.identity.AuthenticationRequestContext;
|
||||
import io.quarkus.security.identity.IdentityProvider;
|
||||
import io.quarkus.security.identity.SecurityIdentity;
|
||||
import io.quarkus.security.identity.request.TrustedAuthenticationRequest;
|
||||
import io.quarkus.security.runtime.QuarkusSecurityIdentity;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import io.vertx.core.http.HttpServerRequest;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
@ApplicationScoped
|
||||
public class HeaderIdentityProvider
|
||||
implements IdentityProvider<TrustedAuthenticationRequest>
|
||||
{
|
||||
|
||||
@Inject
|
||||
HttpServerRequest httpServerRequest;
|
||||
|
||||
@Override
|
||||
public Class<TrustedAuthenticationRequest> getRequestType() {
|
||||
return TrustedAuthenticationRequest.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<SecurityIdentity> authenticate(
|
||||
TrustedAuthenticationRequest request,
|
||||
AuthenticationRequestContext context
|
||||
) {
|
||||
String role = httpServerRequest.getHeader(InternalValue.role);
|
||||
|
||||
return Uni.createFrom().item(
|
||||
QuarkusSecurityIdentity.builder().addRole(role).build()
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user