add calendar module
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
package com.mgm.mcrm;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.mgm.mcrm.appsetting.controllers.CfgSettingController;
|
||||
import com.mgm.mcrm.appsetting.dtos.CfgSettingQueryRequest;
|
||||
import com.mgm.mcrm.appsetting.models.CfgSettings;
|
||||
import com.mgm.mcrm.appsetting.models.SysSetting;
|
||||
import com.mgm.mcrm.appsetting.services.SettingService;
|
||||
import com.mgm.mcrm.appsetting.services.SysSettingService;
|
||||
import com.mgm.mcrm.authorization.services.UserTokenService;
|
||||
import com.mgm.mcrm.common.config.WebFilterConfig;
|
||||
import com.mgm.mcrm.logging.controllers.SysLogAppController;
|
||||
import com.mgm.mcrm.logging.dtos.AppLogDto;
|
||||
import com.mgm.mcrm.logging.models.SysLogApp;
|
||||
import com.mgm.mcrm.logging.services.SysLogAppService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class PublicEndpointsMigrationTest {
|
||||
@Test void publicConfigurationRejectsOtherKeysBeforeQuery() throws Exception {
|
||||
var service = mock(SettingService.class);
|
||||
var controller = new CfgSettingController();
|
||||
ReflectionTestUtils.setField(controller, "settingService", service);
|
||||
for (String key : new String[]{null, "", "MACAU_IP", "macau_string", "MACAU_STRING "}) {
|
||||
var query = new CfgSettingQueryRequest(); query.setKeyName(key);
|
||||
var result = controller.getPublicSettingByKey(new MockHttpServletRequest(), query).getBody();
|
||||
assertFalse(result.isSuccess()); assertEquals("SETTING_KEY_NOT_ALLOWED", result.getCode());
|
||||
}
|
||||
assertFalse(controller.getPublicSettingByKey(new MockHttpServletRequest(), null).getBody().isSuccess());
|
||||
verifyNoInteractions(service);
|
||||
var setting = new CfgSettings();
|
||||
when(service.getSettingByKey("MACAU_STRING")).thenReturn(setting);
|
||||
var query = new CfgSettingQueryRequest(); query.setKeyName("MACAU_STRING");
|
||||
assertSame(setting, controller.getPublicSettingByKey(new MockHttpServletRequest(), query).getBody().getData());
|
||||
verify(service).getSettingByKey("MACAU_STRING");
|
||||
}
|
||||
|
||||
@Test void publicLoginSettingsOnlyFetchTwoAllowedKeysAndAllowMissingSettings() {
|
||||
var service = mock(SysSettingService.class);
|
||||
var controller = new CfgSettingController();
|
||||
ReflectionTestUtils.setField(controller, "sysSettingService", service);
|
||||
var sso = new SysSetting(); var tpd = new SysSetting();
|
||||
when(service.getSysSettingByKey("APP_MOCK_SSO")).thenReturn(sso);
|
||||
when(service.getSysSettingByKey("APP_MOCK_TPD")).thenReturn(tpd);
|
||||
assertEquals(java.util.List.of(sso, tpd), controller.getPublicLoginSettings(new MockHttpServletRequest()).getBody().getData());
|
||||
verify(service).getSysSettingByKey("APP_MOCK_SSO");
|
||||
verify(service).getSysSettingByKey("APP_MOCK_TPD");
|
||||
verifyNoMoreInteractions(service);
|
||||
when(service.getSysSettingByKey("APP_MOCK_TPD")).thenReturn(null);
|
||||
assertEquals(1, controller.getPublicLoginSettings(new MockHttpServletRequest()).getBody().getData().size());
|
||||
}
|
||||
|
||||
@Test void filterAllowsOnlyNewPublicRoutesAndKeepsRefreshProtected() throws Exception {
|
||||
var config = new WebFilterConfig();
|
||||
var tokens = mock(UserTokenService.class);
|
||||
ReflectionTestUtils.setField(config, "secretKey", "test-only-key");
|
||||
ReflectionTestUtils.setField(config, "userTokenService", tokens);
|
||||
var filter = config.jwtAuthFilter().getFilter();
|
||||
for (String route : new String[]{"/system/write_public_log", "/system/sys_setting/get_public_login_settings", "/web/setting/get_public_setting_by_key"}) {
|
||||
var reached = new AtomicBoolean();
|
||||
filter.doFilter(new MockHttpServletRequest("POST", "/api" + route), new MockHttpServletResponse(),
|
||||
(req, res) -> reached.set(true));
|
||||
assertTrue(reached.get(), route);
|
||||
}
|
||||
for (String route : new String[]{"/system/write_log", "/system/sys_setting/get_list", "/web/setting/get_setting_by_key", "/app/booking/mock_cancel", "/app/refresh_token"}) {
|
||||
var reached = new AtomicBoolean(); var response = new MockHttpServletResponse();
|
||||
filter.doFilter(new MockHttpServletRequest("POST", "/api" + route), response, (req, res) -> reached.set(true));
|
||||
assertFalse(reached.get(), route); assertEquals(401, response.getStatus(), route);
|
||||
}
|
||||
}
|
||||
|
||||
private SysLogAppController logs(SysLogAppService service) {
|
||||
var controller = new SysLogAppController();
|
||||
ReflectionTestUtils.setField(controller, "logService", service);
|
||||
when(service.save(any(SysLogApp.class))).thenAnswer(call -> call.getArgument(0));
|
||||
return controller;
|
||||
}
|
||||
|
||||
@Test void anonymousIdentityCannotBeSpoofedAndNullBodiesAreSafe() {
|
||||
var service = mock(SysLogAppService.class); var controller = logs(service);
|
||||
var dto = new AppLogDto(); dto.setLoginId("admin");
|
||||
var result = controller.writePublicAppLog(new MockHttpServletRequest(), dto).getBody().getData();
|
||||
assertEquals("ANONYMOUS", result.getLoginId()); assertNull(result.getLogDesc());
|
||||
assertNull(result.getRequestBody()); assertNull(result.getResponseBody()); assertEquals(0, result.getTagSuccess());
|
||||
assertEquals(400, controller.writePublicAppLog(new MockHttpServletRequest(), null).getStatusCode().value());
|
||||
verify(service, times(1)).save(any(SysLogApp.class));
|
||||
}
|
||||
|
||||
@Test void authenticatedLogUsesTokenIdentityAndRequiresIdentity() {
|
||||
var service = mock(SysLogAppService.class); var controller = logs(service);
|
||||
var dto = new AppLogDto(); dto.setLoginId("forged-user");
|
||||
var request = new MockHttpServletRequest();
|
||||
assertEquals(401, controller.writeAppLog(request, dto).getStatusCode().value());
|
||||
verify(service, never()).save(any());
|
||||
// Controller identity test; JWT admission is covered separately by the filter test.
|
||||
request.addHeader("Authorization", "Bearer " + JWT.create().withSubject("80001")
|
||||
.withClaim("login_id", "actual-user").sign(Algorithm.HMAC256("test-only-key")));
|
||||
assertEquals("actual-user", controller.writeAppLog(request, dto).getBody().getData().getLoginId());
|
||||
}
|
||||
|
||||
@Test void logsLimitInputAndEscapeText() {
|
||||
var controller = logs(mock(SysLogAppService.class));
|
||||
var dto = new AppLogDto(); dto.setEventCode("e".repeat(101)); dto.setTransId("t".repeat(101));
|
||||
dto.setLogDesc("x".repeat(999) + "<ignored"); dto.setRequestBody("r".repeat(4001)); dto.setResponseBody("<script>&");
|
||||
var log = controller.writePublicAppLog(new MockHttpServletRequest(), dto).getBody().getData();
|
||||
assertEquals(100, log.getEventCode().length()); assertEquals(100, log.getTransId().length());
|
||||
assertEquals("x".repeat(999) + "<", log.getLogDesc());
|
||||
assertEquals(4000, log.getRequestBody().length()); assertEquals("<script>&", log.getResponseBody());
|
||||
}
|
||||
|
||||
@Test void httpRejectsMissingAndMalformedLogBodiesWithoutSaving() throws Exception {
|
||||
var service = mock(SysLogAppService.class); var mvc = MockMvcBuilders.standaloneSetup(logs(service)).build();
|
||||
mvc.perform(post("/api/system/write_public_log")).andExpect(status().isBadRequest());
|
||||
mvc.perform(post("/api/system/write_public_log").contentType("application/json")
|
||||
.content("{\"tagSuccess\":\"not-a-number\"}")).andExpect(status().isBadRequest());
|
||||
verify(service, never()).save(any());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.mgm.mcrm;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.mgm.mcrm.authorization.dtos.LoginUserInfo;
|
||||
import com.mgm.mcrm.authorization.models.Token;
|
||||
import com.mgm.mcrm.authorization.repositories.TokenDao;
|
||||
import com.mgm.mcrm.authorization.services.UserTokenService;
|
||||
import com.mgm.mcrm.authorization.utils.JwtTokenUtil;
|
||||
import com.mgm.mcrm.authorization.filters.JwtAuthFilter;
|
||||
import com.mgm.mcrm.common.utils.EncryptUtil;
|
||||
import org.apache.logging.log4j.util.Base64Util;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.mock.web.*;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import java.time.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class RefreshTokenMigrationTest {
|
||||
final Map<String,Token> records = new HashMap<>();
|
||||
TokenDao dao; UserTokenService service; LoginUserInfo user;
|
||||
@BeforeEach void setup() {
|
||||
JwtTokenUtil.setSecretKey("refresh-test-key");
|
||||
ReflectionTestUtils.setField(JwtTokenUtil.class, "verifier", null);
|
||||
JwtTokenUtil.setAccessTokenExpiration(5); JwtTokenUtil.setAppSessionExpiration(30);
|
||||
dao = mock(TokenDao.class); service = new UserTokenService(dao);
|
||||
when(dao.save(any(Token.class))).thenAnswer(c -> {Token t=c.getArgument(0); records.put(t.getUuid(),t); return t;});
|
||||
when(dao.findByUuid(anyString())).thenAnswer(c -> records.get(c.getArgument(0)));
|
||||
when(dao.findByUuidAndTokenType(anyString(),eq(1))).thenAnswer(c -> records.get(c.getArgument(0)));
|
||||
when(dao.deleteByUuidAndTokenType(anyString(),eq(1))).thenAnswer(c -> records.remove(c.getArgument(0)) == null ? 0 : 1);
|
||||
when(dao.deleteByUserIdAndTokenType(anyString(),eq(1))).thenAnswer(c -> {
|
||||
int size=records.size(); records.values().removeIf(t -> c.getArgument(0).equals(t.getCreatedBy())); return size-records.size();
|
||||
});
|
||||
user = new LoginUserInfo(); user.setLoginId("80001"); user.setGroupName("IM");
|
||||
}
|
||||
Token issue(boolean refresh) {return service.saveToken(JwtTokenUtil.generateTokenByLoginUser("/api/app/sso/login",user,1,refresh));}
|
||||
|
||||
@Test void validRefreshPreservesProtocolOwnerGroupAndOriginalRefreshWhenNotRenewing() {
|
||||
Token old=issue(true);
|
||||
var result=service.refreshMobileToken(old.getToken(),"/api/app/refresh_token",false);
|
||||
assertTrue(result.isSuccess()); assertNotNull(result.getAccessToken()); assertNull(result.getRefreshToken());
|
||||
assertNotNull(service.validateMobileRefreshToken(old.getToken()));
|
||||
Token access=service.getToken(result.getAccessToken()); assertEquals("80001",access.getCreatedBy());
|
||||
assertEquals("access",JWT.decode(access.getToken()).getClaim("token_use").asString());
|
||||
assertEquals("IM",JwtTokenUtil.parseUserFromToken(access.getToken()).getGroupName());
|
||||
}
|
||||
@Test void rotationRevokesOldRefreshAndLogoutRevokesAllOwnedCredentials() {
|
||||
Token old=issue(true);
|
||||
var result=service.refreshMobileToken(old.getToken(),"/api/app/refresh_token",true);
|
||||
assertTrue(result.isSuccess()); assertNull(service.validateMobileRefreshToken(old.getToken()));
|
||||
assertNotNull(service.validateMobileRefreshToken(result.getRefreshToken()));
|
||||
assertEquals(2,service.clearTokenByUser("80001",1));
|
||||
assertFalse(service.refreshMobileToken(result.getRefreshToken(),"/api/app/refresh_token",false).isSuccess());
|
||||
}
|
||||
@Test void invalidRevokedExpiredAndAccessCredentialsNeverIssueTokens() {
|
||||
Token refresh=issue(true); Token access=issue(false); int count=records.size();
|
||||
for(String value:new String[]{"", "bad", access.getToken(), refresh.getToken()+"x"})
|
||||
assertFalse(service.refreshMobileToken(value,"/api/app/refresh_token",false).isSuccess());
|
||||
assertEquals(count,records.size());
|
||||
refresh.setExpireTime(LocalDateTime.now().minusSeconds(1));
|
||||
assertNull(service.validateMobileRefreshToken(refresh.getToken()));
|
||||
records.clear(); assertNull(service.validateMobileRefreshToken(refresh.getToken()));
|
||||
}
|
||||
@Test void legacyWrongPurposeWrongTypeAndExpiredSignedTokensRejected() {
|
||||
for(String purpose:new String[]{null,"access","refresh"}) {
|
||||
for(int type:new int[]{0,1}) {
|
||||
String id=UUID.randomUUID().toString();
|
||||
String value=JWT.create().withSubject("80001").withJWTId(id).withClaim("login_id","80001")
|
||||
.withClaim("token_use",purpose).withClaim("token_type",type)
|
||||
.withExpiresAt("refresh".equals(purpose) && type == 1 ? Instant.now().minusSeconds(10) : Instant.now().plusSeconds(300))
|
||||
.sign(Algorithm.HMAC256("refresh-test-key"));
|
||||
Token row=new Token(); row.setUuid(id); row.setToken(value); row.setCreatedBy("80001");
|
||||
row.setExpireTime(LocalDateTime.now().plusMinutes(30)); records.put(id,row);
|
||||
assertNull(service.validateMobileRefreshToken(value));
|
||||
}
|
||||
}
|
||||
Token refresh=issue(true); refresh.setCreatedBy("other-user");
|
||||
assertNull(service.validateMobileRefreshToken(refresh.getToken()));
|
||||
}
|
||||
@Test void filterUsesRefreshHeaderEvenWithExpiredAccessAndRetainsClientCheck() throws Exception {
|
||||
Token refresh=issue(true); var filter=new JwtAuthFilter(); filter.setUserTokenService(service);
|
||||
var request=new MockHttpServletRequest("POST","/api/app/refresh_token");
|
||||
request.addHeader("Authorization",JWT.create().withSubject("80001").withExpiresAt(Instant.now().minusSeconds(60))
|
||||
.sign(Algorithm.HMAC256("refresh-test-key"))); request.addHeader("RefreshToken",refresh.getToken());
|
||||
request.addHeader("clientId",EncryptUtil.sha256(Base64Util.encode("mcrm_80001")));
|
||||
var reached=new AtomicBoolean(); var response=new MockHttpServletResponse();
|
||||
filter.doFilter(request,response,(req,res)->reached.set(true)); assertTrue(reached.get());
|
||||
request.removeHeader("clientId"); reached.set(false); response=new MockHttpServletResponse();
|
||||
filter.doFilter(request,response,(req,res)->reached.set(true)); assertFalse(reached.get());
|
||||
}
|
||||
@Test void refreshCannotAuthorizeBusinessRequests() throws Exception {
|
||||
var filter=new JwtAuthFilter(); filter.setUserTokenService(service);
|
||||
var request=new MockHttpServletRequest("POST","/api/app/me");
|
||||
request.addHeader("Authorization",issue(true).getToken());
|
||||
var response=new MockHttpServletResponse(); var reached=new AtomicBoolean();
|
||||
filter.doFilter(request,response,(req,res)->reached.set(true));
|
||||
assertFalse(reached.get()); assertEquals(401,response.getStatus());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.mgm.mcrm;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.parser.Feature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mgm.mcrm.common.dtos.mgm_api.TodoDetailResult;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class TodoIrcMigrationTest {
|
||||
@Test
|
||||
void upstreamBalanceSurvivesParsingAndAppSerialization() throws Exception {
|
||||
for (String amount : new String[]{"0", "1234.50"}) {
|
||||
TodoDetailResult detail = JSONObject.parseObject(
|
||||
"{\"IRCProgramFundBalance\":\"" + amount + "\"}",
|
||||
TodoDetailResult.class, Feature.SupportNonPublicField, Feature.IgnoreNotMatch);
|
||||
assertEquals(amount, detail.getIrcProgramFundBalance());
|
||||
assertEquals(amount, new ObjectMapper().valueToTree(detail).get("iRCProgramFundBalance").asText());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.mgm.mcrm;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.parser.Feature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mgm.mcrm.common.dtos.mgm_api.TodoDetailResult;
|
||||
import com.mgm.mcrm.common.dtos.mgm_api.TodoListRecord;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class TodoNumericMigrationTest {
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
private JsonNode detail(String json) {
|
||||
return mapper.valueToTree(JSONObject.parseObject(json, TodoDetailResult.class,
|
||||
Feature.SupportNonPublicField, Feature.IgnoreNotMatch));
|
||||
}
|
||||
@Test void numericFieldsPreserveDecimalsLargeNumbersZeroAndNull() {
|
||||
String[][] fields = {{"PrgTO","prgTO"},{"PrgWin","prgWin"},{"FrontMoney","frontMoney"},
|
||||
{"TTO","tto"},{"01CompBalance","comBalance"},{"ExpComm","expComm"},
|
||||
{"NetCreditOutstanding","netCreditOutstanding"},{"UnsettledExpenses","unsettledExpenses"},
|
||||
{"TodayTo","todayTo"},{"TodayTPD","todayTPD"},{"TodayWin","todayWin"},{"TodayTheo","todayTheo"},
|
||||
{"TripWin","tripWin"},{"TripTPD","tripTPD"},{"TripTheo","tripTheo"},
|
||||
{"TripRIPercentage","tripRIPercentage"},{"YesterdayTO","yesterdayTO"},{"YesterdayWin","yesterdayWin"},
|
||||
{"YesterdayPlayHour","yesterdayPlayHour"},{"AveragePlayHour","averagePlayHour"}};
|
||||
for (String[] field : fields) {
|
||||
for (String value : new String[]{"12.75","3000000000","0","-12.75"}) {
|
||||
for (String input : new String[]{value, "\"" + value + "\""}) {
|
||||
JsonNode result = detail("{\"" + field[0] + "\":" + input + "}").get(field[1]);
|
||||
assertNotNull(result, field[1]); assertTrue(result.isTextual(), field[1]);
|
||||
assertEquals(value, result.asText(), field[0]);
|
||||
}
|
||||
}
|
||||
assertTrue(detail("{\"" + field[0] + "\":null}").get(field[1]).isNull());
|
||||
}
|
||||
}
|
||||
@Test void aliasesAndDaylightOnlyDetailFieldsRemain() {
|
||||
var result = detail("{\"01CompBalance\":\"37.50\",\"TORIPercentage\":0.25,\"HouseAdvantagePercentage\":\"0.1\",\"IRCProgramFundBalance\":\"99\"}");
|
||||
assertEquals("37.50", result.get("comBalance").asText());
|
||||
assertEquals("37.50", result.get("01CompBalance").asText());
|
||||
assertEquals(0.25, result.get("toripercentage").asDouble());
|
||||
assertEquals("0.1", result.get("HouseAdvantagePercentage").asText());
|
||||
assertEquals("99", result.get("iRCProgramFundBalance").asText());
|
||||
}
|
||||
@Test void listPreservesMaidEtaAndRoomFlagsAlongsideMaId() {
|
||||
var record = JSONObject.parseObject("{\"MAId\":123,\"ETA\":\"13:45\"}", TodoListRecord.class,
|
||||
Feature.SupportNonPublicField, Feature.IgnoreNotMatch);
|
||||
record.setRoomReady(true); record.setIsQueue(true);
|
||||
JsonNode result = mapper.valueToTree(record);
|
||||
assertEquals(123,result.get("maid").asInt());assertEquals(123,result.get("maId").asInt());
|
||||
assertEquals("13:45",result.get("eta").asText());
|
||||
assertTrue(result.get("roomReady").asBoolean());assertTrue(result.get("isQueue").asBoolean());
|
||||
assertFalse(result.has("calendarMaId"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.mgm.mcrm;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mgm.mcrm.common.dtos.mgm_api.*;
|
||||
import com.mgm.mcrm.player.services.TodoService;
|
||||
import com.mgm.mcrm.player.dtos.request.TodoCancelBookingRequest;
|
||||
import com.mgm.mcrm.appsetting.services.SysSettingService;
|
||||
import com.mgm.mcrm.booking.models.*;
|
||||
import com.mgm.mcrm.booking.repositories.*;
|
||||
import com.mgm.mcrm.booking.services.OperaService;
|
||||
import com.mgm.mcrm.basesetting.property.repositories.PropertyDao;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import java.util.Optional;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class TodoRemainingContractTest {
|
||||
@Test void remainingDtosPreservePascalInputAndCamelOutput() {
|
||||
var mapper = new ObjectMapper();
|
||||
var list=JSONObject.parseObject("{\"StatusCode\":\"0\",\"StatusDescription\":\"OK\",\"Records\":[{\"MAId\":80001}]}",TodoListResult.class);
|
||||
var json=mapper.valueToTree(list);
|
||||
assertEquals("0",json.get("statusCode").asText());
|
||||
assertEquals("OK",json.get("statusDescription").asText());
|
||||
assertEquals(80001,json.get("records").get(0).get("maId").asInt());
|
||||
var dates=JSONObject.parseObject("{\"StatusCode\":\"0\",\"Records\":[{\"Date\":\"2026-09-10\",\"DateRecords\":[{\"MAId\":80001}]}]}",TodoDateListResult.class);
|
||||
var date=mapper.valueToTree(dates).get("records").get(0);
|
||||
assertEquals("2026-09-10",date.get("date").asText());
|
||||
assertEquals(80001,date.get("dateRecords").get(0).get("maId").asInt());
|
||||
var description=JSONObject.parseObject("{\"ItemRecordType\":\"Offer\",\"ItemRecordId\":42,\"ItemRecordDescription\":\"Room\"}",TodoDetailDescription.class);
|
||||
var detail=mapper.valueToTree(description);
|
||||
assertEquals("Offer",detail.get("itemRecordType").asText());
|
||||
assertEquals(42,detail.get("itemRecordId").asInt());
|
||||
assertEquals("Room",detail.get("itemRecordDescription").asText());
|
||||
}
|
||||
|
||||
@Test void nullOperaCancellationReturnsFailureInsteadOfThrowing() throws Exception {
|
||||
var service=new TodoService(); var views=mock(BookingViewDao.class); var bookings=mock(BookingDao.class);
|
||||
var opera=mock(OperaService.class); var settings=mock(SysSettingService.class);
|
||||
ReflectionTestUtils.setField(service,"bookingViewDao",views);
|
||||
ReflectionTestUtils.setField(service,"bookingDao",bookings);
|
||||
ReflectionTestUtils.setField(service,"operaService",opera);
|
||||
ReflectionTestUtils.setField(service,"sysSettingService",settings);
|
||||
ReflectionTestUtils.setField(service,"propertyDao",mock(PropertyDao.class));
|
||||
var view=new BookingsView(); view.setPropertyCategory("OPERA"); view.setConfirmationNo("test-confirmation");
|
||||
var booking=new Bookings();
|
||||
when(views.findById(Long.valueOf(42))).thenReturn(Optional.of(view));
|
||||
when(bookings.findById(42L)).thenReturn(Optional.of(booking));
|
||||
when(opera.fetchBooking(any())).thenReturn(new JSONObject());
|
||||
when(opera.cancelBooking(any())).thenReturn(null);
|
||||
var request=new TodoCancelBookingRequest(); request.setId(42L);
|
||||
var result=service.cancelBooking(request,new MockHttpServletRequest());
|
||||
assertFalse(result.isSuccess()); assertEquals("SYSTEM_ERROR",result.getCode());
|
||||
assertEquals("Cancel Booking Fail",result.getMessage());
|
||||
assertEquals("Cancel Booking Fail",booking.getErrorMessage());
|
||||
assertEquals("F",booking.getApproveStatus());
|
||||
verify(opera,times(1)).cancelBooking(any());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.mgm.mcrm.roomcalendar;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mgm.mcrm.appsetting.controllers.CfgSettingController;
|
||||
import com.mgm.mcrm.appsetting.models.CfgSettings;
|
||||
import com.mgm.mcrm.appsetting.repositories.SettingDao;
|
||||
import com.mgm.mcrm.appsetting.services.SettingService;
|
||||
import com.mgm.mcrm.authorization.models.SysGroupPermission;
|
||||
import com.mgm.mcrm.authorization.models.SysUserView;
|
||||
import com.mgm.mcrm.authorization.repositories.*;
|
||||
import com.mgm.mcrm.authorization.services.MgmUserService;
|
||||
import com.mgm.mcrm.authorization.services.UserTokenService;
|
||||
import com.mgm.mcrm.basesetting.property.repositories.*;
|
||||
import com.mgm.mcrm.basesetting.team.repositories.*;
|
||||
import com.mgm.mcrm.common.config.WebFilterConfig;
|
||||
import com.mgm.mcrm.common.dtos.http_util.HttpResponseResult;
|
||||
import com.mgm.mcrm.common.services.MGMApiService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import java.util.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CalendarBootstrapMigrationTest {
|
||||
@Mock MGMApiService esb;
|
||||
@Mock PropertyDao propertyDao;
|
||||
@Mock BlockDao blockDao;
|
||||
@Mock DivisionDao divisionDao;
|
||||
@Mock DepartmentDao departmentDao;
|
||||
@Mock SectionDao sectionDao;
|
||||
@Mock TeamStructureDao teamStructureDao;
|
||||
@Mock SysUserViewDao users;
|
||||
@Mock SysGroupPermissionDao permissions;
|
||||
@InjectMocks MgmUserService userService;
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings={"allowed","denied","no-local-user"})
|
||||
void calendarPermissionComesFromLocalGroupAndKeepsBookingPermission(String mode) throws Exception {
|
||||
HttpResponseResult upstream = new HttpResponseResult();
|
||||
upstream.setStatusCode(200);
|
||||
upstream.setResponseContent("{\"StatusCode\":\"OK\",\"Records\":[{\"userId\":\"123\",\"userName\":\"Tester\",\"canViewCalendar\":true}]}");
|
||||
when(esb.invokeGetUserInfo("123","")).thenReturn(upstream);
|
||||
if (!mode.equals("no-local-user")) {
|
||||
SysUserView user = new SysUserView();
|
||||
user.setGroupId(7L); user.setGroupName("test-group");
|
||||
when(users.getByLoginId("123")).thenReturn(user);
|
||||
SysGroupPermission booking = new SysGroupPermission();
|
||||
booking.setPermissionId("10001_01");
|
||||
SysGroupPermission calendar = new SysGroupPermission();
|
||||
calendar.setPermissionId("10001_07");
|
||||
when(permissions.getAllByGroupId(7L)).thenReturn(
|
||||
mode.equals("allowed") ? List.of(booking,calendar) : List.of(booking));
|
||||
}
|
||||
var result = userService.findUserInfoByUserId("123");
|
||||
assertTrue(result.isSuccess(),result.getMessage());
|
||||
var json = new ObjectMapper().valueToTree(result.getData());
|
||||
assertEquals(mode.equals("allowed"),json.get("canViewCalendar").asBoolean());
|
||||
assertEquals(!mode.equals("no-local-user"),result.getData().isCanViewBooking());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans={true,false})
|
||||
void mockSwitchOnlyGrantsCalendarWithoutGroupConfiguration(boolean enabled) throws Exception {
|
||||
ReflectionTestUtils.setField(userService,"calendarPermissionMockEnabled",enabled);
|
||||
HttpResponseResult upstream = new HttpResponseResult();
|
||||
upstream.setStatusCode(200);
|
||||
upstream.setResponseContent("{\"StatusCode\":\"OK\",\"Records\":[{\"userId\":\"123\"}]}");
|
||||
when(esb.invokeGetUserInfo("123","")).thenReturn(upstream);
|
||||
var result = userService.findUserInfoByUserId("123");
|
||||
assertTrue(result.isSuccess(),result.getMessage());
|
||||
assertEquals(enabled,result.getData().isCanViewCalendar());
|
||||
assertFalse(result.getData().isCanViewBooking());
|
||||
verifyNoInteractions(permissions);
|
||||
}
|
||||
|
||||
CfgSettings setting(String key,String value) {
|
||||
CfgSettings setting = new CfgSettings();
|
||||
setting.setKeys(key); setting.setKeyValues(value);
|
||||
return setting;
|
||||
}
|
||||
|
||||
@Test void calendarSettingsExposeOnlyFiveExactKeysAndPreserveValues() throws Exception {
|
||||
List<String> keys = List.of("CALENDAR_VIEW_PREVIOUS_DAYS","CALENDAR_VIEW_VISIBLE_DAYS",
|
||||
"CALENDAR_VIEW_YESTERDAY_START","CALENDAR_VIEW_YESTERDAY_END","MAX_SELECTED_ROOM_TYPES");
|
||||
List<CfgSettings> rows = new ArrayList<>();
|
||||
for (String key : keys) rows.add(setting(key,"3"));
|
||||
rows.add(setting("OTHER_SETTING","private"));
|
||||
rows.add(setting("calendar_view_previous_days","wrong-case"));
|
||||
rows.add(setting(null,"missing-key"));
|
||||
rows.add(null);
|
||||
SettingDao dao = mock(SettingDao.class);
|
||||
when(dao.findAll()).thenReturn(rows);
|
||||
SettingService service = new SettingService();
|
||||
ReflectionTestUtils.setField(service,"settingDao",dao);
|
||||
CfgSettingController controller = new CfgSettingController();
|
||||
ReflectionTestUtils.setField(controller,"settingService",service);
|
||||
var result = controller.getCalendarSetting();
|
||||
assertEquals(200,result.getStatusCode().value());
|
||||
assertTrue(result.getBody().isSuccess());
|
||||
assertEquals(keys,result.getBody().getData().stream().map(CfgSettings::getKeys).toList());
|
||||
var json = new ObjectMapper().valueToTree(result.getBody());
|
||||
assertEquals("3",json.get("data").get(0).get("keyValues").asText());
|
||||
}
|
||||
|
||||
@Test void missingSettingsReturnEmptyListWithoutInventedDefaults() {
|
||||
SettingDao dao = mock(SettingDao.class);
|
||||
when(dao.findAll()).thenReturn(List.of());
|
||||
SettingService service = new SettingService();
|
||||
ReflectionTestUtils.setField(service,"settingDao",dao);
|
||||
assertTrue(service.getCalendarSetting().isEmpty());
|
||||
}
|
||||
|
||||
@Test void calendarSettingsRouteRemainsBehindExistingJwtFilter() throws Exception {
|
||||
WebFilterConfig config = new WebFilterConfig();
|
||||
ReflectionTestUtils.setField(config,"secretKey","calendar-test-only-secret");
|
||||
ReflectionTestUtils.setField(config,"userTokenService",mock(UserTokenService.class));
|
||||
var filter = config.jwtAuthFilter().getFilter();
|
||||
var request = new MockHttpServletRequest("POST","/api/app/setting/get_calendar_setting");
|
||||
var response = new MockHttpServletResponse();
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
filter.doFilter(request,response,chain);
|
||||
assertEquals(401,response.getStatus());
|
||||
verifyNoInteractions(chain);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.mgm.mcrm.roomcalendar;
|
||||
|
||||
import com.mgm.mcrm.roomcalendar.services.*;
|
||||
import com.mgm.mcrm.appsetting.services.SettingService;
|
||||
import com.mgm.mcrm.appsetting.repositories.SettingDao;
|
||||
import com.mgm.mcrm.basesetting.property.repositories.PropertyDao;
|
||||
import com.mgm.mcrm.basesetting.room.repositories.RoomDao;
|
||||
import com.mgm.mcrm.common.services.MGMApiService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import java.util.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class CalendarMockDataTest {
|
||||
@Test void catalogAndQueriesAgreeForEveryHotelAcrossMonthBoundary() {
|
||||
var catalog = CalendarMockData.metadata().getPropertyList();
|
||||
var hotels = new ArrayList<>(catalog.subList(0,2));
|
||||
hotels.addAll(catalog.get(2).getOtherProperties());
|
||||
assertEquals(6,hotels.size());
|
||||
int count=0;
|
||||
for (var hotel:hotels) {
|
||||
assertTrue(hotel.getName().contains("[MOCK]"));
|
||||
String rooms=String.join(",",hotel.getRoomTypes().stream().map(t->t.getCode()).toList());
|
||||
var rows=CalendarMockData.records("",hotel.getCode(),rooms,"2026-09-28","2026-10-03");
|
||||
assertEquals(hotel.getRoomTypes().size()*6,rows.size());
|
||||
assertTrue(rows.stream().anyMatch(row->row.getDate().equals("2026-10-01")));
|
||||
assertEquals(rows,CalendarMockData.records("",hotel.getCode(),rooms,"2026-09-28","2026-10-03"));
|
||||
count+=rows.size();
|
||||
}
|
||||
assertEquals(96,count);
|
||||
}
|
||||
|
||||
@Test void variedAvailabilityAndPlayerQualificationAreDeterministic() {
|
||||
var rows=CalendarMockData.records("80001","SIM_COTAI","CR,ES","2026-09-01","2026-10-31");
|
||||
assertTrue(rows.stream().anyMatch(r->r.getRoomCount()==0));
|
||||
assertTrue(rows.stream().anyMatch(r->r.getRoomCount()>0));
|
||||
assertEquals(Set.of(0,1),new HashSet<>(rows.stream().map(r->r.getBookingDateQualificationFlag()).toList()));
|
||||
assertNotEquals(rows,CalendarMockData.records("80002","SIM_COTAI","CR,ES","2026-09-01","2026-10-31"));
|
||||
assertEquals(4,CalendarMockData.records("","SIM_MO,SIM_LB","MO_STD,LB_GRAND","2026-09-01","2026-09-02").size());
|
||||
}
|
||||
|
||||
@Test void invalidRequestsFailInsteadOfProducingPlausibleData() {
|
||||
assertThrows(IllegalArgumentException.class,()->CalendarMockData.records("","MC","CR","2026-09-01","2026-09-02"));
|
||||
assertThrows(IllegalArgumentException.class,()->CalendarMockData.records("","SIM_COTAI","GR","2026-09-01","2026-09-02"));
|
||||
assertThrows(IllegalArgumentException.class,()->CalendarMockData.records("","SIM_COTAI","CR","2026-09-02","2026-09-01"));
|
||||
assertThrows(IllegalArgumentException.class,()->CalendarMockData.records("","SIM_COTAI","CR","2026-01-01","2026-12-31"));
|
||||
}
|
||||
|
||||
@Test void enabledMocksDoNotReadDatabaseOrCallEsbAndDisabledSettingsUseDatabase() throws Exception {
|
||||
var service=new RoomCalendarService();
|
||||
var properties=mock(PropertyDao.class); var rooms=mock(RoomDao.class); var esb=mock(MGMApiService.class);
|
||||
ReflectionTestUtils.setField(service,"propertyDao",properties);
|
||||
ReflectionTestUtils.setField(service,"roomDao",rooms);
|
||||
ReflectionTestUtils.setField(service,"mgmApiService",esb);
|
||||
ReflectionTestUtils.setField(service,"calendarDataMockEnabled",true);
|
||||
assertEquals(3,service.getPropertyRoomType().getPropertyList().size());
|
||||
var result=service.getRoomCalendar(Map.of("Property","SIM_COTAI","RoomType","CR",
|
||||
"StartDate","2026-09-01","EndDate","2026-09-03"));
|
||||
assertTrue(result.isSuccess()); assertEquals(3,result.getData().size());
|
||||
assertEquals("CALENDAR_MOCK_DATA",result.getMessage());
|
||||
verifyNoInteractions(properties,rooms,esb);
|
||||
var settings=new SettingService(); var dao=mock(SettingDao.class);
|
||||
ReflectionTestUtils.setField(settings,"settingDao",dao);
|
||||
ReflectionTestUtils.setField(settings,"calendarDataMockEnabled",true);
|
||||
assertEquals("60",settings.getCalendarSetting().stream()
|
||||
.filter(s->s.getKeys().equals("CALENDAR_VIEW_VISIBLE_DAYS")).findFirst().orElseThrow().getKeyValues());
|
||||
verifyNoInteractions(dao);
|
||||
ReflectionTestUtils.setField(settings,"calendarDataMockEnabled",false);
|
||||
when(dao.findAll()).thenReturn(List.of());
|
||||
assertTrue(settings.getCalendarSetting().isEmpty()); verify(dao).findAll();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
package com.mgm.mcrm.roomcalendar;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mgm.mcrm.authorization.dtos.LoginUserInfo;
|
||||
import com.mgm.mcrm.authorization.services.SysGroupPermissionService;
|
||||
import com.mgm.mcrm.authorization.utils.JwtTokenUtil;
|
||||
import com.mgm.mcrm.basesetting.property.models.CfgProperties;
|
||||
import com.mgm.mcrm.basesetting.property.repositories.PropertyDao;
|
||||
import com.mgm.mcrm.basesetting.room.models.CfgRooms;
|
||||
import com.mgm.mcrm.basesetting.room.repositories.RoomDao;
|
||||
import com.mgm.mcrm.common.dtos.http_util.HttpResponseResult;
|
||||
import com.mgm.mcrm.common.services.MGMApiService;
|
||||
import com.mgm.mcrm.roomcalendar.controllers.RoomCalendarController;
|
||||
import com.mgm.mcrm.roomcalendar.repositories.RoomCalendarRoomProjection;
|
||||
import com.mgm.mcrm.roomcalendar.services.RoomCalendarService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import java.util.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class CalendarQueryMigrationTest {
|
||||
PropertyDao properties;
|
||||
RoomDao rooms;
|
||||
MGMApiService esb;
|
||||
RoomCalendarService service;
|
||||
|
||||
@BeforeEach void setup() {
|
||||
properties = mock(PropertyDao.class);
|
||||
rooms = mock(RoomDao.class);
|
||||
esb = mock(MGMApiService.class);
|
||||
service = new RoomCalendarService();
|
||||
ReflectionTestUtils.setField(service, "propertyDao", properties);
|
||||
ReflectionTestUtils.setField(service, "roomDao", rooms);
|
||||
ReflectionTestUtils.setField(service, "mgmApiService", esb);
|
||||
}
|
||||
|
||||
Map<String,Object> request(boolean pascal) {
|
||||
Map<String,Object> result = new HashMap<>();
|
||||
result.put(pascal ? "Property" : "property", "Macau");
|
||||
result.put(pascal ? "RoomType" : "roomType", "SUITE");
|
||||
result.put(pascal ? "StartDate" : "startDate", "2026-09-10");
|
||||
result.put(pascal ? "EndDate" : "endDate", "2026-09-12");
|
||||
return result;
|
||||
}
|
||||
|
||||
CfgProperties property(long id, String name, String category, int order) {
|
||||
CfgProperties p = new CfgProperties();
|
||||
p.setId(id); p.setCalendarName(name); p.setName(name);
|
||||
p.setCode("MO"); p.setCategory(category);
|
||||
p.setCalendarOrder(order); p.setShowCalendar(1);
|
||||
return p;
|
||||
}
|
||||
|
||||
void visible() {
|
||||
when(properties.findByCalendarNameIn(any())).thenReturn(List.of(property(1,"Macau","OPERA",1)));
|
||||
CfgRooms room = new CfgRooms();
|
||||
room.setPropertyId("1"); room.setCalendarName("SUITE"); room.setShowCalendar(1);
|
||||
when(rooms.findByPropertyIdInAndCalendarNameIn(List.of("1"),List.of("SUITE")))
|
||||
.thenReturn(List.of(room));
|
||||
}
|
||||
|
||||
HttpResponseResult response(int status, String body) {
|
||||
HttpResponseResult response = new HttpResponseResult();
|
||||
response.setStatusCode(status); response.setResponseContent(body);
|
||||
return response;
|
||||
}
|
||||
|
||||
@ParameterizedTest @ValueSource(booleans={true,false})
|
||||
void aliasesResolveCalendarNameToEsbCodeAndNormalizeResponse(boolean pascal) throws Exception {
|
||||
visible();
|
||||
when(esb.invokeRequestRoomCalendar("","MO","SUITE","2026-09-10","2026-09-12",0))
|
||||
.thenReturn(response(200,"{\"StatusCode\":\"OK\",\"Records\":[{\"Property\":\"MO\",\"RoomType\":\"SUITE\",\"Date\":\"2026-09-10T00:00:00\",\"RoomCriteria\":\"A\",\"RoomCount\":3,\"PropertyLeader\":\"L\",\"BookingDateQualificationFlag\":1}]}"));
|
||||
var result = service.getRoomCalendar(request(pascal));
|
||||
assertTrue(result.isSuccess());
|
||||
assertEquals("2026-09-10",result.getData().getFirst().getDate());
|
||||
assertEquals(3,result.getData().getFirst().getRoomCount());
|
||||
verify(esb).invokeRequestRoomCalendar("","MO","SUITE","2026-09-10","2026-09-12",0);
|
||||
}
|
||||
|
||||
@Test void missingInputDoesNotCallDatabaseOrEsb() throws Exception {
|
||||
assertFalse(service.getRoomCalendar(Map.of()).isSuccess());
|
||||
verifyNoInteractions(properties,rooms,esb);
|
||||
}
|
||||
|
||||
@Test void hiddenPropertyDoesNotReachRoomLookupOrEsb() throws Exception {
|
||||
CfgProperties p = property(1,"Macau","OPERA",1); p.setShowCalendar(0);
|
||||
when(properties.findByCalendarNameIn(any())).thenReturn(List.of(p));
|
||||
var result = service.getRoomCalendar(request(true));
|
||||
assertEquals("PROPERTYNOSHOW",result.getErrorCode());
|
||||
verifyNoInteractions(rooms,esb);
|
||||
}
|
||||
|
||||
@Test void hiddenRoomDoesNotReachEsb() throws Exception {
|
||||
visible();
|
||||
CfgRooms hidden = new CfgRooms(); hidden.setCalendarName("SUITE"); hidden.setShowCalendar(0);
|
||||
when(rooms.findByPropertyIdInAndCalendarNameIn(anyList(),anyList())).thenReturn(List.of(hidden));
|
||||
assertEquals("ROOMTYPENOSHOW",service.getRoomCalendar(request(true)).getErrorCode());
|
||||
verifyNoInteractions(esb);
|
||||
}
|
||||
|
||||
@ParameterizedTest @ValueSource(ints={200,503})
|
||||
void upstreamFailureIsNotEmptySuccess(int status) throws Exception {
|
||||
visible();
|
||||
when(esb.invokeRequestRoomCalendar(anyString(),anyString(),anyString(),anyString(),anyString(),anyInt()))
|
||||
.thenReturn(response(status,"{\"StatusCode\":\"FAIL\",\"StatusDescription\":\"Rejected\"}"));
|
||||
assertFalse(service.getRoomCalendar(request(true)).isSuccess());
|
||||
}
|
||||
|
||||
RoomCalendarRoomProjection projected(String propertyId,String name,int order) {
|
||||
var row = mock(RoomCalendarRoomProjection.class);
|
||||
when(row.getPropertyId()).thenReturn(propertyId);
|
||||
when(row.getCalendarName()).thenReturn(name);
|
||||
when(row.getCalendarOrder()).thenReturn(order);
|
||||
when(row.getDefaultShowCalendar()).thenReturn(1);
|
||||
return row;
|
||||
}
|
||||
|
||||
@ParameterizedTest @ValueSource(strings={"OPERA","DAYLIGHT"})
|
||||
void metadataOrdersRoomsCapsDefaultsAndGroupsOtherProperties(String category) {
|
||||
CfgProperties hidden = property(3,"Hidden",category,0); hidden.setShowCalendar(0);
|
||||
when(properties.findAll()).thenReturn(new ArrayList<>(List.of(
|
||||
property(2,"Other Hotel","OTHER",2),hidden,property(1,"Macau",category,1))));
|
||||
List<RoomCalendarRoomProjection> projectedRooms = List.of(
|
||||
projected("1","D",4), projected("1","B",2), projected("1","A",1),
|
||||
projected("1","C",3), projected("2","X",1));
|
||||
when(rooms.queryCalendarRoomsByPropertyIds(anyList())).thenReturn(projectedRooms);
|
||||
var result = service.getPropertyRoomType();
|
||||
assertTrue(result.isSuccess());
|
||||
assertEquals(2,result.getPropertyList().size());
|
||||
var macau = result.getPropertyList().getFirst();
|
||||
assertEquals("Macau",macau.getCode());
|
||||
assertEquals(List.of("A","B","C"),macau.getDefaultRoomTypes());
|
||||
var other = result.getPropertyList().get(1);
|
||||
assertEquals("OTHER",other.getCode());
|
||||
assertEquals(List.of("Other Hotel"),other.getDefaultRoomTypes());
|
||||
assertEquals("X",other.getOtherProperties().getFirst().getRoomTypes().getFirst().getCode());
|
||||
verifyNoInteractions(esb);
|
||||
}
|
||||
|
||||
@Test void daylightCalendarUsesConfiguredPropertyCodeAndRoomCalendarName() throws Exception {
|
||||
CfgProperties daylight = property(1090,"Cotai","DAYLIGHT",1);
|
||||
daylight.setCode("configured-daylight-code");
|
||||
when(properties.findByCalendarNameIn(List.of("Cotai"))).thenReturn(List.of(daylight));
|
||||
CfgRooms room = new CfgRooms();
|
||||
room.setPropertyId("1090"); room.setCalendarName("configured-room-name"); room.setShowCalendar(1);
|
||||
when(rooms.findByPropertyIdInAndCalendarNameIn(List.of("1090"),List.of("configured-room-name")))
|
||||
.thenReturn(List.of(room));
|
||||
when(esb.invokeRequestRoomCalendar("","configured-daylight-code","configured-room-name","2026-09-10","2026-09-12",1))
|
||||
.thenReturn(response(200,"{\"StatusCode\":\"OK\",\"Records\":[]}"));
|
||||
var payload = request(true);
|
||||
payload.put("Property","Cotai"); payload.put("RoomType","configured-room-name");
|
||||
assertTrue(service.getRoomCalendar(payload).isSuccess());
|
||||
verify(esb).invokeRequestRoomCalendar("","configured-daylight-code","configured-room-name","2026-09-10","2026-09-12",1);
|
||||
}
|
||||
|
||||
@ParameterizedTest @ValueSource(strings={"","12345"})
|
||||
void esbAdapterUsesAuthenticatedPostAndOptionalPlayer(String player) throws Exception {
|
||||
MGMApiService adapter = spy(new MGMApiService());
|
||||
doReturn("test-token").when(adapter).getAccessToken();
|
||||
HttpResponseResult expected = response(200,"{}");
|
||||
doAnswer(call -> {
|
||||
assertEquals("/RequestRoomCalendar",call.getArgument(1));
|
||||
com.alibaba.fastjson.JSONObject body = call.getArgument(2);
|
||||
assertEquals("MO",body.getString("Property"));
|
||||
assertEquals("SUITE",body.getString("RoomType"));
|
||||
assertEquals("2026-09-10",body.getString("StartDate"));
|
||||
assertEquals("2026-09-12",body.getString("EndDate"));
|
||||
assertEquals(player.isEmpty() ? null : player,body.getString("PlayerId"));
|
||||
assertEquals("POST",call.getArgument(3));
|
||||
assertEquals(Map.of("Authorization","test-token"),call.getArgument(4));
|
||||
return expected;
|
||||
}).when(adapter).invokeESBAPI(anyString(),anyString(),any(),anyString(),anyMap(),anyInt());
|
||||
assertSame(expected,adapter.invokeRequestRoomCalendar(player,"MO","SUITE","2026-09-10","2026-09-12"));
|
||||
}
|
||||
|
||||
@Test void permittedPlayerRequestReachesServiceWithoutLosingPayload() throws Exception {
|
||||
RoomCalendarController controller = new RoomCalendarController();
|
||||
RoomCalendarService queries = mock(RoomCalendarService.class);
|
||||
SysGroupPermissionService permissions = mock(SysGroupPermissionService.class);
|
||||
ReflectionTestUtils.setField(controller,"roomCalendarService",queries);
|
||||
ReflectionTestUtils.setField(controller,"sysGroupPermissionService",permissions);
|
||||
MockHttpServletRequest req = new MockHttpServletRequest();
|
||||
LoginUserInfo user = new LoginUserInfo(); user.setGroupName("calendar-users");
|
||||
when(permissions.checkGroupPermission("calendar-users","10001_07")).thenReturn(true);
|
||||
Map<String,Object> payload = request(true); payload.put("PlayerId","12345");
|
||||
var expected = new com.mgm.mcrm.roomcalendar.dtos.response.RoomCalendarApiResponse<java.util.List<com.mgm.mcrm.roomcalendar.dtos.RoomCalendarQualification>>();
|
||||
expected.setSuccess(true);
|
||||
when(queries.getRoomCalendar(payload)).thenReturn(expected);
|
||||
try (var jwt = mockStatic(JwtTokenUtil.class)) {
|
||||
jwt.when(() -> JwtTokenUtil.parseUserFromRequest(req)).thenReturn(user);
|
||||
assertSame(expected,controller.getPlayerRoomQualification(req,payload));
|
||||
verify(queries).getRoomCalendar(payload);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest @ValueSource(booleans={true,false})
|
||||
void mockPermissionAllowsAllCalendarRoutesButStillRequiresUser(boolean loggedIn) throws Exception {
|
||||
RoomCalendarController controller = new RoomCalendarController();
|
||||
RoomCalendarService queries = mock(RoomCalendarService.class);
|
||||
SysGroupPermissionService permissions = mock(SysGroupPermissionService.class);
|
||||
ReflectionTestUtils.setField(controller,"roomCalendarService",queries);
|
||||
ReflectionTestUtils.setField(controller,"sysGroupPermissionService",permissions);
|
||||
ReflectionTestUtils.setField(controller,"calendarPermissionMockEnabled",true);
|
||||
MockHttpServletRequest req = new MockHttpServletRequest();
|
||||
try (var jwt = mockStatic(JwtTokenUtil.class)) {
|
||||
jwt.when(() -> JwtTokenUtil.parseUserFromRequest(req))
|
||||
.thenReturn(loggedIn ? new LoginUserInfo() : null);
|
||||
var general = controller.requestRoomCalendar(req,request(true));
|
||||
var player = controller.getPlayerRoomQualification(req,request(true));
|
||||
var metadata = controller.requestPropertiesRoomTypes(req);
|
||||
if (loggedIn) {
|
||||
verify(queries,times(2)).getRoomCalendar(request(true));
|
||||
verify(queries).getPropertyRoomType();
|
||||
} else {
|
||||
assertEquals("NO_PERMISSION",general.getErrorCode());
|
||||
assertEquals("NO_PERMISSION",player.getErrorCode());
|
||||
assertEquals("NO_PERMISSION",metadata.getErrorCode());
|
||||
verifyNoInteractions(queries);
|
||||
}
|
||||
verifyNoInteractions(permissions);
|
||||
}
|
||||
}
|
||||
|
||||
@Test void allControllerRoutesRejectDeniedGroupAndSerializeCompatibleErrors() throws Exception {
|
||||
RoomCalendarController controller = new RoomCalendarController();
|
||||
RoomCalendarService queries = mock(RoomCalendarService.class);
|
||||
SysGroupPermissionService permissions = mock(SysGroupPermissionService.class);
|
||||
ReflectionTestUtils.setField(controller,"roomCalendarService",queries);
|
||||
ReflectionTestUtils.setField(controller,"sysGroupPermissionService",permissions);
|
||||
MockHttpServletRequest req = new MockHttpServletRequest();
|
||||
LoginUserInfo user = new LoginUserInfo(); user.setGroupName("restricted");
|
||||
try (var jwt = mockStatic(JwtTokenUtil.class)) {
|
||||
jwt.when(() -> JwtTokenUtil.parseUserFromRequest(req)).thenReturn(user);
|
||||
var result = controller.requestRoomCalendar(req,request(true));
|
||||
var json = new ObjectMapper().valueToTree(result);
|
||||
assertEquals("NO_PERMISSION",json.get("code").asText());
|
||||
assertEquals("NO_PERMISSION",json.get("errorCode").asText());
|
||||
assertEquals("NO_PERMISSION",controller.getPlayerRoomQualification(req,request(true)).getErrorCode());
|
||||
assertEquals("NO_PERMISSION",controller.requestPropertiesRoomTypes(req).getErrorCode());
|
||||
verify(permissions,times(3)).checkGroupPermission("restricted","10001_07");
|
||||
verifyNoInteractions(queries);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user