diff --git a/src/main/resources/static/css/navBar.css b/src/main/resources/static/css/navBar.css index 9676ecacf21f7a34785ee25ac11478ec6f50bd34..8ff90dffa0e60c3947e07ad0b38aac2e0d59538d 100644 --- a/src/main/resources/static/css/navBar.css +++ b/src/main/resources/static/css/navBar.css @@ -46,14 +46,21 @@ body { background-color: #444; border-radius: 5px; } -.navbar .auth-buttons button { - padding: 10px 20px; - margin-left: 10px; - border: none; - border-radius: 5px; - cursor: pointer; + +.navbar .auth-buttons { + display: flex; + flex-direction: column; + button { + padding: 10px 20px; + margin-left: 10px; + border: none; + border-radius: 5px; + cursor: pointer; + } } + + .navbar .auth-buttons .login-btn { background-color: #007BFF; width: 100px; diff --git a/src/main/resources/static/html/matchDetail.html b/src/main/resources/static/html/matchDetail.html index fe9da877b5ac5de2909b2e80a6086dc9f557c2e7..504dfd3ce4e338089fa40908e5e6c84ddf699fa1 100644 --- a/src/main/resources/static/html/matchDetail.html +++ b/src/main/resources/static/html/matchDetail.html @@ -3,13 +3,125 @@ <head> <meta charset="UTF-8"> <title>Match Detail</title> + <style> + * { + margin: 0; + padding: 0; + box-sizing: border-box; + } + + body { + font-family: Arial, sans-serif; + background-color: #f4f4f4; + color: #333; + } + .title-h1{ + h1 { + background-color: #4a4a4a; + p { + font-size: 36px; + color: white; + + font-weight: bold; + text-align: center; + } + + } + } + .container { + width: 80%; + margin: 20px auto; + } + + header { + text-align: center; + margin-bottom: 30px; + } + #matchDetails { + margin-left: 45px; + align-items: center; + background-color: #fff; + border-radius: 12px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + width: 100%; + max-width: 900px; + padding: 30px; + box-sizing: border-box; + margin-top: 30px; + } + + h2 { + text-align: center; + font-size: 2.5em; + color: #333; + margin-bottom: 20px; + } + + #matchScore { + font-size: 2.4em; + line-height: 1.6; + color: #444; + margin: 20px 0; + } + + #matchScore p { + text-align: center; + } + + #matchInfo { + font-size: 1.2em; + line-height: 1.6; + color: #444; + } + + #matchInfo p { + margin: 15px 0; + padding: 10px; + background-color: #f9f9f9; + border-radius: 6px; + } + + strong { + color: #2d2d2d; + } + /*adjust for phone*/ + @media screen and (max-width: 768px) { + .container { + width: 95%; + } + + .match-item { + flex-direction: column; + align-items: flex-start; + } + } + + </style> + <link rel="stylesheet" href="/css/navBar.css"> + <link rel="stylesheet" href="/css/footer.css"> </head> <body> - <div id="matchDetails"> - <h2>Match Details</h2> - <div id="matchInfo"></div> + <!-- navbar--> + + <div id="navbar-container"></div> + <div class="title-h1"> + <h1><p>Match Details</p></h1> + </div> + <div class="container"> + <div id="matchDetails"> + <h2>Match Details</h2> + <div id="matchScore"></div> + <div id="matchInfo"></div> + </div> </div> + <div id="footer-container"></div> + <script src="/js/navBar.js"></script> + <script src="/js/footer.js"></script> + <script> + loadNavbar('navbar-container'); + loadFooter('footer-container'); + </script> </body> <script> const urlParams = new URLSearchParams(window.location.search); @@ -21,12 +133,14 @@ const matchData = await response.json(); const matchInfo = document.getElementById('matchInfo'); + const matchScore = document.getElementById('matchScore'); + matchScore.innerHTML = `<p><strong></strong>${matchData.scoreA} - ${matchData.scoreB}</p> +` matchInfo.innerHTML = ` <p><strong>Sport: </strong>${matchData.sport}</p> <p><strong>Players: </strong>${matchData.playerAId} vs ${matchData.playerBId}</p> <p><strong>Scheduled Time: </strong>${new Date(matchData.planTime).toLocaleString()}</p> <p><strong>Status: </strong>${matchData.status}</p> - <p><strong>Score: </strong>${matchData.scoreA} - ${matchData.scoreB}</p> <p><strong>Winner: </strong>${matchData.winnerId ? matchData.winnerId : 'N/A'}</p> `; } catch (error) { diff --git a/src/main/resources/static/html/matchSchedule.html b/src/main/resources/static/html/matchSchedule.html index 33e53eb58d1167e673fa815176d7a44c798e610b..0be587d9c331158f16076a59c10b3834fcd3ac33 100644 --- a/src/main/resources/static/html/matchSchedule.html +++ b/src/main/resources/static/html/matchSchedule.html @@ -3,9 +3,10 @@ <head> <meta charset="UTF-8"> <title>Sports league Schedule</title> - <link rel="stylesheet" href="/css/matchSchedule.css"> <link rel="stylesheet" href="/css/navBar.css"> <link rel="stylesheet" href="/css/footer.css"> + <link rel="stylesheet" href="/css/matchSchedule.css"> + </head> <body> <!-- navbar--> @@ -44,7 +45,7 @@ <!-- generate match in there --> </div> </div> - <!-- navbar--> + <!-- footer--> <div id="footer-container"></div> <script src="/js/navBar.js"></script> <script src="/js/footer.js"></script> diff --git a/src/test/java/uk/ac/cf/spring/demo/MatchControllerTest.java b/src/test/java/uk/ac/cf/spring/demo/MatchControllerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a1a39daff8130fc5f7d5be03974d6923de5cd8d2 --- /dev/null +++ b/src/test/java/uk/ac/cf/spring/demo/MatchControllerTest.java @@ -0,0 +1,61 @@ +package uk.ac.cf.spring.demo; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import uk.ac.cf.spring.demo.sports.match.MatchController; +import uk.ac.cf.spring.demo.sports.match.MatchItem; +import uk.ac.cf.spring.demo.sports.match.MatchService; + +import java.util.Arrays; +import java.util.List; + +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class MatchControllerTest { + + @Mock + private MatchService matchService; + + @InjectMocks + private MatchController matchController; + + private MockMvc mockMvc; + + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.standaloneSetup(matchController).build(); + } + + @Test + void testGetAllMatches() throws Exception { + MatchItem match1 = new MatchItem(1L, "Soccer", 1L, 2L, null, "completed", 2L, 3L, true, true, 2L); + List<MatchItem> matches = Arrays.asList(match1); + + when(matchService.getMatchItems()).thenReturn(matches); + + mockMvc.perform(get("/match")) + .andExpect(status().isOk()); + + verify(matchService, times(1)).getMatchItems(); + } + + @Test + void testGetMatchById() throws Exception { + MatchItem match1 = new MatchItem(1L, "Soccer", 1L, 2L, null, "completed", 2L, 3L, true, true, 2L); + + when(matchService.getMatchItemById(1L)).thenReturn(match1); + + mockMvc.perform(get("/match/1")) + .andExpect(status().isOk()); + + verify(matchService, times(1)).getMatchItemById(1L); + } +} diff --git a/src/test/java/uk/ac/cf/spring/demo/MatchServiceTest.java b/src/test/java/uk/ac/cf/spring/demo/MatchServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a45d45c29b4ba8e311c9a79cc925b52d3ecf92a2 --- /dev/null +++ b/src/test/java/uk/ac/cf/spring/demo/MatchServiceTest.java @@ -0,0 +1,69 @@ +package uk.ac.cf.spring.demo; + +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 uk.ac.cf.spring.demo.sports.match.MatchItem; +import uk.ac.cf.spring.demo.sports.match.MatchRepository; +import uk.ac.cf.spring.demo.sports.match.MatchServiceListImpl; + +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; + +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(MockitoExtension.class) // 使得 Mockito 能够工作 +public class MatchServiceTest { + + @Mock + private MatchRepository matchRepository; // 模拟 MatchRepository + + @InjectMocks + private MatchServiceListImpl matchService; // 注入 MatchServiceListImpl + + private MatchItem matchItem1; + private MatchItem matchItem2; + + @BeforeEach + public void setUp() { + // 设置一些初始的 MatchItem 数据 + matchItem1 = new MatchItem(1L, "Soccer", 1L, 2L, LocalDateTime.now(), "pending", 0L, 0L, false, false, 0L); + matchItem2 = new MatchItem(2L, "Basketball", 3L, 4L, LocalDateTime.now(), "pending", 0L, 0L, false, false, 0L); + } + + @Test + public void testGetMatchItems() { + + when(matchRepository.getMatchItems()).thenReturn(Arrays.asList(matchItem1, matchItem2)); + List<MatchItem> matchItems = matchService.getMatchItems(); + assertNotNull(matchItems); + assertEquals(2, matchItems.size()); + assertEquals("Soccer", matchItems.get(0).getSport()); + assertEquals("Basketball", matchItems.get(1).getSport()); + verify(matchRepository, times(1)).getMatchItems(); + } + + @Test + public void testGetMatchItemById() { + + when(matchRepository.getMatchItemById(1L)).thenReturn(matchItem1); + MatchItem matchItem = matchService.getMatchItemById(1L); + assertNotNull(matchItem); + assertEquals(1L, matchItem.getId()); + assertEquals("Soccer", matchItem.getSport()); + + verify(matchRepository, times(1)).getMatchItemById(1L); + } + + @Test + public void testAddMatchItem() { + MatchItem newMatchItem = new MatchItem(0L, "Tennis", 5L, 6L, LocalDateTime.now(), "pending", 0L, 0L, false, false, 0L); + matchService.addMatchItem(newMatchItem); + verify(matchRepository, times(1)).addMatchItem(newMatchItem); + } +}