Skip to content
Snippets Groups Projects
Commit bf6370e0 authored by Xiemuqing Xiao's avatar Xiemuqing Xiao
Browse files

Merge remote-tracking branch 'origin/main'

parents c5c5c802 9ebf61d8
No related branches found
No related tags found
No related merge requests found
Showing
with 1204 additions and 40 deletions
......@@ -2,6 +2,7 @@ plugins {
id 'java'
id 'org.springframework.boot' version '3.3.5'
id 'io.spring.dependency-management' version '1.1.6'
id 'jacoco' // 引入 JaCoCo 插件
}
group = 'uk.ac.cf.spring'
......@@ -28,20 +29,27 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
//from https://mariadb.com/kb/en/java-connector-using-gradle/
implementation 'junit:junit:4.12'
implementation 'org.mariadb.jdbc:mariadb-java-client:3.3.3'
// implementation 'org.mariadb.jdbc:mariadb-java-client:2.1.2'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.mariadb.jdbc:mariadb-java-client'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-security'
compileOnly 'org.projectlombok:lombok'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation 'org.springframework.security:spring-security-test'
// testImplementation("io.github.bonigarcia:webdrivermanager:5.2.0")
// testImplementation group: 'net.sourceforge.htmlunit', name: 'htmlunit', version: '2.32'
// testImplementation group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '4.1.0'
}
tasks.named('test') {
......
......@@ -26,6 +26,7 @@ public class SecurityConfig {
"/api/**", // API
"/html/**", // static HTML
"/html/register.html", // register
"/register",
"/html/login.html", // login
"/html/table-tennisrules.html",
"/html/login.html" , // login
......@@ -46,9 +47,7 @@ public class SecurityConfig {
.anyRequest().authenticated() // 其他页面需要认证
)
.csrf().disable()
// .formLogin(form -> form
// .loginPage("/login").permitAll() // 定义自定义登录页面
// )
.formLogin(form -> form
.loginPage("/html/login.html").permitAll() // 使用自定义页面
.defaultSuccessUrl("/html/matchSchedule.html", true) // 登录成功后跳转
......
......@@ -18,7 +18,7 @@ public class RegistrationController {
@GetMapping("/register")
public String showRegistrationForm() {
return "page/register"; // return register.html
return "html/register.html"; // return register.html
}
......
CREATE DATABASE IF NOT EXISTS sports;
USE sports;
drop table if exists match_item;
drop table if exists ranking;
drop table if exists information;
......
CREATE DATABASE IF NOT EXISTS sports;
USE sports;
drop table if exists match_item;
drop table if exists ranking;
drop table if exists information;
drop table if exists images;
CREATE TABLE information (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
role VARCHAR(20) DEFAULT 'USER' NOT NULL
);
create table if not exists match_item (
-- Match ID
id BIGINT AUTO_INCREMENT PRIMARY KEY,
-- Sport type
sport ENUM('Pools', 'Darts', 'TableTennis') NOT NULL,
-- Player A ID
player_AId INT NULL,
-- Player B ID
player_BId INT NULL,
plan_Time DATETIME NOT NULL,
-- Match status
status ENUM('pending', 'confirmed', 'completed') DEFAULT 'pending',
score_a INT DEFAULT 0,
score_b INT DEFAULT 0,
confirm_a BOOLEAN DEFAULT FALSE,
confirm_b BOOLEAN DEFAULT FALSE,
winner_id BIGINT DEFAULT NULL
# FOREIGN KEY (player_AId) REFERENCES information(id) ON DELETE CASCADE,
# FOREIGN KEY (player_BId) REFERENCES information(id) ON DELETE CASCADE
# FOREIGN KEY (player_AId) REFERENCES information(id) ON DELETE SET NULL,
# FOREIGN KEY (player_BId) REFERENCES information(id) ON DELETE SET NULL
);
CREATE TABLE IF NOT EXISTS ranking (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
sport ENUM('Pools', 'Darts', 'TableTennis') NOT NULL,
wins INT DEFAULT 0,
username VARCHAR(255) DEFAULT NULL,
UNIQUE (user_id, sport) -- 添加唯一约束
);
CREATE TABLE images (
id INT AUTO_INCREMENT PRIMARY KEY,
url VARCHAR(255) NOT NULL, -- 图片文件名或路径
uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP-- 上传时间
);
delete from information;
delete from match_item;
delete from ranking;
INSERT INTO information (id, username, email, password, role)
VALUES (1, 'shy', 'shy@creditsafe.com', '$2a$16$R0aSGzbklUhpRfIMhocewephgUDMFOffLb7faSwwHusqHh81G026i', 'USER');
INSERT INTO information (id, username, email, password, role)
VALUES (2, 'zyb', 'zyb@creditsafe.com', '$2a$16$R0aSGzbklUhpRfIMhocewephgUDMFOffLb7faSwwHusqHh81G026i', 'USER');
INSERT INTO information (id, username, email, password, role)
VALUES (3, 'xzc', 'xzc@creditsafe.com', '$2a$16$R0aSGzbklUhpRfIMhocewephgUDMFOffLb7faSwwHusqHh81G026i', 'USER');
INSERT INTO information (id, username, email, password, role)
VALUES (4, 'xx', 'xx@creditsafe.com', '$2a$16$R0aSGzbklUhpRfIMhocewephgUDMFOffLb7faSwwHusqHh81G026i', 'USER');
insert into match_item (sport, player_AId, player_BId, plan_Time, status, score_a, score_b, confirm_a, confirm_b, winner_id)
values
-- test data
-- 1: Pending status
('Pools', 1, 2, '2024-11-25 14:30:00', 'pending', 0, 0, FALSE, FALSE, NULL),
-- 2: Confirmed status, Player 3 wins
('Darts', 3, 4, '2024-11-26 16:00:00', 'confirmed', 3, 2, TRUE, TRUE, 3),
-- 3: Completed status, Player 6 wins
('TableTennis', 1, 2, '2024-11-27 18:00:00', 'completed', 21, 18, TRUE, TRUE, 2),
-- 4: Pending status
('Pools', 2, 1, '2024-11-28 20:00:00', 'pending', 0, 0, FALSE, FALSE, NULL),
-- 5: Completed status, Player 9 wins
('Darts', 1, 2, '2024-11-29 15:30:00', 'completed', 300, 280, TRUE, TRUE, 2),
-- 6: Confirmed status, Player 1 wins
('TableTennis', 1, 2, '2024-11-30 17:00:00', 'confirmed', 3, 1, TRUE, TRUE, 1),
('TableTennis', null, null, '2024-12-20 17:00:00', 'pending', 0, 0, false, false, null),
('TableTennis', null, null, '2024-12-21 17:00:00', 'pending', 0, 0, false, false, null),
('Pools', null, null, '2024-12-22 17:00:00', 'pending', 0, 0, false, false, null),
('Pools', null, null, '2024-12-23 17:00:00', 'pending', 0, 0, false, false, null),
('Pools', null, null, '2024-12-24 17:00:00', 'pending', 0, 0, false, false, null),
('Darts', null, null, '2024-12-25 17:00:00', 'pending', 0, 0, false, false, null),
('Darts', null, null, '2024-12-26 17:00:00', 'pending', 0, 0, false, false, null),
('Darts', null, null, '2024-12-27 17:00:00', 'pending', 0, 0, false, false, null);
INSERT INTO ranking (user_id,username,sport, wins) VALUES
(1, 'shy','Pools', 0),
(1, 'shy','Darts', 0),
(1, 'shy','TableTennis', 0),
(2, 'zyb','Pools', 0),
(2, 'zyb','Darts', 0),
(2, 'zyb','TableTennis', 0),
(3, 'xzc','Pools', 0),
(3, 'xzc','Darts', 0),
(3, 'xzc','TableTennis', 0),
(4, 'xx','Pools', 0),
(4, 'xx','Darts', 0),
(4, 'xx','TableTennis', 0);
......@@ -19,7 +19,7 @@ function loadNavbar(targetElementId) {
document.getElementById(targetElementId).innerHTML = data;
// After the navbar is loaded, check and update user authentication state
updateAuthButtons();
// updateAuthButtons();
})
.catch(error => {
console.error('loadNav errors:', error);
......@@ -27,34 +27,34 @@ function loadNavbar(targetElementId) {
}
// Update authentication buttons based on user login state
function updateAuthButtons() {
fetch('/users/current', { method: 'GET' })
.then(response => {
if (!response.ok) {
throw new Error('User not logged in');
}
return response.json();
})
.then(data => {
// If logged in, update Login button to display username
const authBtn = document.getElementById('auth-btn');
authBtn.textContent = data.username;
authBtn.href = '#'; // Disable navigation for username display
authBtn.classList.remove('login-btn');
authBtn.classList.add('username-btn');
// Show the Logout button
document.getElementById('logout-btn').style.display = 'block';
})
.catch(() => {
// If not logged in, reset the buttons to default state
const authBtn = document.getElementById('auth-btn');
authBtn.textContent = 'Login';
authBtn.href = '/html/login.html'; // Link back to the login page
authBtn.classList.add('login-btn');
authBtn.classList.remove('username-btn');
// Hide the Logout button
document.getElementById('logout-btn').style.display = 'none';
});
}
// function updateAuthButtons() {
// fetch('/users/current', { method: 'GET' })
// .then(response => {
// if (!response.ok) {
// throw new Error('User not logged in');
// }
// return response.json();
// })
// .then(data => {
// // If logged in, update Login button to display username
// const authBtn = document.getElementById('auth-btn');
// authBtn.textContent = data.username;
// authBtn.href = '#'; // Disable navigation for username display
// authBtn.classList.remove('login-btn');
// authBtn.classList.add('username-btn');
//
// // Show the Logout button
// document.getElementById('logout-btn').style.display = 'block';
// })
// .catch(() => {
// // If not logged in, reset the buttons to default state
// const authBtn = document.getElementById('auth-btn');
// authBtn.textContent = 'Login';
// authBtn.href = '/html/login.html'; // Link back to the login page
// authBtn.classList.add('login-btn');
// authBtn.classList.remove('username-btn');
//
// // Hide the Logout button
// document.getElementById('logout-btn').style.display = 'none';
// });
// }
......@@ -6,6 +6,6 @@
<link rel="stylesheet" href="../../css/index.css">
</head>
<body>
<p>index.html</p>
<p>index.html1</p>
</body>
</html>
\ No newline at end of file
{
"id": "16ffd25e-f706-4a5e-812c-fbb9b11e75cc",
"version": "2.0",
"name": "sportsLeagueTest",
"url": "http://localhost:8080",
"tests": [{
"id": "0664bd87-4218-41d5-833e-1d7ce52c2608",
"name": "testLoginandMatchTest",
"commands": [{
"id": "209c5b55-a832-4a2b-9372-e728e2c7aca6",
"comment": "",
"command": "open",
"target": "/html/login.html",
"targets": [],
"value": ""
}, {
"id": "5c887cdc-2af2-4872-b805-045796a73e08",
"comment": "",
"command": "setWindowSize",
"target": "652x672",
"targets": [],
"value": ""
}, {
"id": "6159b882-bf7e-4a0c-a26a-699e36d738fd",
"comment": "",
"command": "click",
"target": "id=email",
"targets": [
["id=email", "id"],
["name=email", "name"],
["css=#email", "css:finder"],
["xpath=//input[@id='email']", "xpath:attributes"],
["xpath=//form[@id='loginForm']/input", "xpath:idRelative"],
["xpath=//input", "xpath:position"]
],
"value": ""
}, {
"id": "b4176d53-16e3-4162-8c95-d4dbf0a4ba3c",
"comment": "",
"command": "type",
"target": "id=email",
"targets": [
["id=email", "id"],
["name=email", "name"],
["css=#email", "css:finder"],
["xpath=//input[@id='email']", "xpath:attributes"],
["xpath=//form[@id='loginForm']/input", "xpath:idRelative"],
["xpath=//input", "xpath:position"]
],
"value": "shy@creditsafe.com"
}, {
"id": "8248a227-e5d9-43e7-859a-aff3c895e870",
"comment": "",
"command": "click",
"target": "id=password",
"targets": [
["id=password", "id"],
["name=password", "name"],
["css=#password", "css:finder"],
["xpath=//input[@id='password']", "xpath:attributes"],
["xpath=//form[@id='loginForm']/input[2]", "xpath:idRelative"],
["xpath=//input[2]", "xpath:position"]
],
"value": ""
}, {
"id": "73cfb95a-0326-48e4-b97a-06369d4eb339",
"comment": "",
"command": "type",
"target": "id=password",
"targets": [
["id=password", "id"],
["name=password", "name"],
["css=#password", "css:finder"],
["xpath=//input[@id='password']", "xpath:attributes"],
["xpath=//form[@id='loginForm']/input[2]", "xpath:idRelative"],
["xpath=//input[2]", "xpath:position"]
],
"value": "shy"
}, {
"id": "44b3048d-06b1-4a31-be86-28dff3f52d98",
"comment": "",
"command": "click",
"target": "css=button",
"targets": [
["css=button", "css:finder"],
["xpath=//button[@type='submit']", "xpath:attributes"],
["xpath=//form[@id='loginForm']/button", "xpath:idRelative"],
["xpath=//button", "xpath:position"],
["xpath=//button[contains(.,'Login')]", "xpath:innerText"]
],
"value": ""
}, {
"id": "5f6090f4-5d83-417c-8a49-7b85e60a580b",
"comment": "",
"command": "click",
"target": "id=sportSelect",
"targets": [
["id=sportSelect", "id"],
["css=#sportSelect", "css:finder"],
["xpath=//select[@id='sportSelect']", "xpath:attributes"],
["xpath=//select", "xpath:position"]
],
"value": ""
}, {
"id": "983cf95d-9003-4cda-9e7f-b6ad1b8873a8",
"comment": "",
"command": "select",
"target": "id=sportSelect",
"targets": [],
"value": "label=Pools"
}, {
"id": "b286ccc1-6cad-4701-b408-50086c7184a1",
"comment": "",
"command": "click",
"target": "id=sportSelect",
"targets": [
["id=sportSelect", "id"],
["css=#sportSelect", "css:finder"],
["xpath=//select[@id='sportSelect']", "xpath:attributes"],
["xpath=//select", "xpath:position"]
],
"value": ""
}, {
"id": "1441088d-98fa-436d-b89c-923b26c5c272",
"comment": "",
"command": "select",
"target": "id=sportSelect",
"targets": [],
"value": "label=Darts"
}, {
"id": "565747ec-9749-4145-9313-0a5ae850264c",
"comment": "",
"command": "click",
"target": "id=sportSelect",
"targets": [
["id=sportSelect", "id"],
["css=#sportSelect", "css:finder"],
["xpath=//select[@id='sportSelect']", "xpath:attributes"],
["xpath=//select", "xpath:position"]
],
"value": ""
}, {
"id": "7a51ec33-f510-4479-8aea-4a1f3522174a",
"comment": "",
"command": "select",
"target": "id=sportSelect",
"targets": [],
"value": "label=Table Tennis"
}, {
"id": "950a1838-f63d-4d69-a83f-01926ff620c2",
"comment": "",
"command": "click",
"target": "id=sportSelect",
"targets": [
["id=sportSelect", "id"],
["css=#sportSelect", "css:finder"],
["xpath=//select[@id='sportSelect']", "xpath:attributes"],
["xpath=//select", "xpath:position"]
],
"value": ""
}, {
"id": "d5e44974-5e91-4255-8715-1794a9f6cbfe",
"comment": "",
"command": "select",
"target": "id=sportSelect",
"targets": [],
"value": "label=All Sports"
}, {
"id": "3d13848c-e203-471a-bc44-e0b8d60a8fd9",
"comment": "",
"command": "click",
"target": "id=statusSelect",
"targets": [
["id=statusSelect", "id"],
["css=#statusSelect", "css:finder"],
["xpath=//select[@id='statusSelect']", "xpath:attributes"],
["xpath=//select[2]", "xpath:position"]
],
"value": ""
}, {
"id": "8e084da0-e59b-4ac9-b50e-dc609086e34e",
"comment": "",
"command": "select",
"target": "id=statusSelect",
"targets": [],
"value": "label=Pending"
}, {
"id": "e023b21b-ed4a-4454-9aab-a93a741636f8",
"comment": "",
"command": "click",
"target": "id=statusSelect",
"targets": [
["id=statusSelect", "id"],
["css=#statusSelect", "css:finder"],
["xpath=//select[@id='statusSelect']", "xpath:attributes"],
["xpath=//select[2]", "xpath:position"]
],
"value": ""
}, {
"id": "cabca20b-76d7-493d-bee1-bf3dbaa34760",
"comment": "",
"command": "select",
"target": "id=statusSelect",
"targets": [],
"value": "label=Confirmed"
}, {
"id": "fb3a64d1-e62c-41db-acde-91dca7b84a39",
"comment": "",
"command": "click",
"target": "id=statusSelect",
"targets": [
["id=statusSelect", "id"],
["css=#statusSelect", "css:finder"],
["xpath=//select[@id='statusSelect']", "xpath:attributes"],
["xpath=//select[2]", "xpath:position"]
],
"value": ""
}, {
"id": "b372f9e9-eb79-47c2-b82a-11cbdf162f93",
"comment": "",
"command": "select",
"target": "id=statusSelect",
"targets": [],
"value": "label=Completed"
}, {
"id": "d6905fbf-9814-49c2-bff6-b7cd4ffd0186",
"comment": "",
"command": "click",
"target": "id=statusSelect",
"targets": [
["id=statusSelect", "id"],
["css=#statusSelect", "css:finder"],
["xpath=//select[@id='statusSelect']", "xpath:attributes"],
["xpath=//select[2]", "xpath:position"]
],
"value": ""
}, {
"id": "6eed2c7c-107f-48e9-a0dd-06ad5555caea",
"comment": "",
"command": "select",
"target": "id=statusSelect",
"targets": [],
"value": "label=All Sports"
}, {
"id": "0f56e0a9-75b0-40c7-a7c6-5ad2e4a07fd5",
"comment": "",
"command": "click",
"target": "id=sortTimeBtn",
"targets": [
["id=sortTimeBtn", "id"],
["css=#sortTimeBtn", "css:finder"],
["xpath=//button[@id='sortTimeBtn']", "xpath:attributes"],
["xpath=//div[2]/button", "xpath:position"],
["xpath=//button[contains(.,'Sort by Time')]", "xpath:innerText"]
],
"value": ""
}, {
"id": "0a21d7ae-0c6f-4136-94a6-8d544f42633c",
"comment": "",
"command": "click",
"target": "id=sortTimeBtn",
"targets": [
["id=sortTimeBtn", "id"],
["css=#sortTimeBtn", "css:finder"],
["xpath=//button[@id='sortTimeBtn']", "xpath:attributes"],
["xpath=//div[2]/button", "xpath:position"],
["xpath=//button[contains(.,'Sort by Time')]", "xpath:innerText"]
],
"value": ""
}, {
"id": "b985fc2e-1068-455b-b212-23c940790db5",
"comment": "",
"command": "click",
"target": "css=.match-item:nth-child(1)",
"targets": [
["css=.match-item:nth-child(1)", "css:finder"],
["xpath=//div[@id='matchesList']/div", "xpath:idRelative"],
["xpath=//div[3]/div[3]/div", "xpath:position"]
],
"value": ""
}, {
"id": "a02a6189-a333-4149-bd8c-696869367f06",
"comment": "",
"command": "click",
"target": "id=updateBtn",
"targets": [
["id=updateBtn", "id"],
["css=#updateBtn", "css:finder"],
["xpath=//button[@id='updateBtn']", "xpath:attributes"],
["xpath=//div[@id='matchDetails']/button", "xpath:idRelative"],
["xpath=//button", "xpath:position"],
["xpath=//button[contains(.,'Update Score')]", "xpath:innerText"]
],
"value": ""
}, {
"id": "69365172-4d89-44d1-8959-1bf8d3f6db26",
"comment": "",
"command": "click",
"target": "id=matchDetails",
"targets": [
["id=matchDetails", "id"],
["css=#matchDetails", "css:finder"],
["xpath=//div[@id='matchDetails']", "xpath:attributes"],
["xpath=//div[3]/div", "xpath:position"]
],
"value": ""
}, {
"id": "d3db7118-ff77-4602-8e55-fcb0c7d1264f",
"comment": "",
"command": "type",
"target": "id=scoreA",
"targets": [
["id=scoreA", "id"],
["name=scoreA", "name"],
["css=#scoreA", "css:finder"],
["xpath=//input[@id='scoreA']", "xpath:attributes"],
["xpath=//form[@id='updateMatchForm']/input", "xpath:idRelative"],
["xpath=//input", "xpath:position"]
],
"value": "1"
}, {
"id": "d78e77a7-1fd2-4acc-a5b1-0f785d6b6ccc",
"comment": "",
"command": "click",
"target": "css=button:nth-child(23)",
"targets": [
["css=button:nth-child(23)", "css:finder"],
["xpath=//button[@type='submit']", "xpath:attributes"],
["xpath=//form[@id='updateMatchForm']/button", "xpath:idRelative"],
["xpath=//button", "xpath:position"],
["xpath=//button[contains(.,'Update Score')]", "xpath:innerText"]
],
"value": ""
}]
}],
"suites": [{
"id": "c5b624ea-1ae7-4147-b21a-7ebf68e013d9",
"name": "Default Suite",
"persistSession": false,
"parallel": false,
"timeout": 300,
"tests": ["0664bd87-4218-41d5-833e-1d7ce52c2608"]
}],
"urls": ["http://localhost:8080/"],
"plugins": []
}
\ No newline at end of file
//package uk.ac.cf.spring.demo;
//import org.junit.jupiter.api.AfterEach;
//import org.junit.jupiter.api.BeforeAll;
//import org.junit.jupiter.api.BeforeEach;
//import org.junit.jupiter.api.Test;
//import org.junit.runner.RunWith;
//import org.openqa.selenium.By;
//import org.openqa.selenium.WebDriver;
//import org.openqa.selenium.chrome.ChromeDriver;
//import org.openqa.selenium.chrome.ChromeOptions;
//import org.openqa.selenium.firefox.FirefoxDriver;
//import org.openqa.selenium.firefox.FirefoxOptions;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.boot.test.context.SpringBootTest;
//import org.springframework.test.context.junit4.SpringRunner;
//
//import io.github.bonigarcia.wdm.WebDriverManager;
//
//
//import static org.junit.Assert.assertTrue;
//@RunWith(SpringRunner.class)
//@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
//public class ChromeDriverTest {
//
// @Value("${local.server.port}")
// private int port;
// WebDriver webDriver;
// @BeforeEach
// void setupTest() {
//// ChromeOptions options = new ChromeOptions();
// FirefoxOptions options = new FirefoxOptions();
//// options.addArguments("--remote-debugging-port=42227");
// options.addArguments("--headless");
//// webDriver = new ChromeDriver(options);
// webDriver = new FirefoxDriver(options);
// }
//
// @AfterEach
// public void teardown() {
// // 关闭浏览器
// if (webDriver != null) {
// webDriver.quit();
// }
// }
//
// @Test
// public void greetingShouldReturnDefaultMessage() throws Exception {
// webDriver.get("http://localhost:" + port + "/html/matchSchedule.html");
//
// assertTrue(webDriver.getPageSource().contains("Sport"));
// }
// @Test
// public void loginAndSeeLoginMessage() throws Exception {
// webDriver.get("http://localhost:" + port + "/html/login.html");
//
// webDriver.findElement(By.name("email")).sendKeys("shy@creditsafe.com");
// webDriver.findElement(By.name("password")).sendKeys("shy");
//
// webDriver.findElement(By.xpath("//button[text()='Login']")).click();
//
// Thread.sleep(2000);
//
// assertTrue(webDriver.getPageSource().contains("Login successful"));
// }
// }
//
package uk.ac.cf.spring.demo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;
import java.util.HashMap;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HTTPConnectionTest {
// 通过 Spring 注入的端口
@Value(value = "${local.server.port}")
private int port;
// RestTemplate 用于发送 HTTP 请求
@Autowired
private TestRestTemplate restTemplate;
// 提取常量,避免在每个测试方法中重复
private String baseUrl() {
return "http://localhost:" + port;
}
// 测试页面加载是否包含指定内容
@Test
public void greetingShouldReturnDefaultMessage() throws Exception {
String url = baseUrl() + "/html/matchSchedule.html";
// 使用 RestTemplate 发送 GET 请求并检查返回内容
String response = this.restTemplate.getForObject(url, String.class);
// 检查响应中是否包含 "Sport" 字样
assertThat(response).contains("Sport");
}
// 测试数据库接口(模拟用户登录并检查后续请求)
@Test
public void dbMatchTest() throws Exception {
String loginUrl = baseUrl() + "/api/users/login";
String matchUrl = baseUrl() + "/match";
// 准备登录数据
Map<String, String> loginData = new HashMap<>();
loginData.put("email", "shy@creditsafe.com");
loginData.put("password", "shy");
// 发送 POST 请求模拟登录
ResponseEntity<String> loginResponse = this.restTemplate.postForEntity(loginUrl, loginData, String.class);
// 验证登录成功消息
assertThat(loginResponse.getBody()).contains("Login successful");
// 检查 match 接口返回的内容是否包含 "Pools" 字段
String matchResponse = this.restTemplate.getForObject(matchUrl, String.class);
assertThat(matchResponse).contains("Pools");
}
}
package uk.ac.cf.spring.demo;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
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 uk.ac.cf.spring.demo.sports.security.SecurityConfig;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import static org.mockito.Mockito.when;
//Lightweight Mock MVC
// Unit or Integration
@RunWith(SpringRunner.class)
@WebMvcTest(MatchController.class)
@Import(SecurityConfig.class)
public class LightweightMockMVCTests {
@Autowired
private MockMvc mockMvc;
@MockBean
private MatchService matchService;
@WithMockUser(username = "shy", password = "shy")
@Test
public void testGetAllMatchItems() throws Exception {
// Prepare match items with specific data
MatchItem matchItem1 = new MatchItem(1L, "Pools", 1L, 2L, LocalDateTime.now(), "pending", 0L, 0L, false, false, 0L);
MatchItem matchItem2 = new MatchItem(2L, "Darts", 3L, 4L, LocalDateTime.now(), "pending", 0L, 0L, false, false, 0L);
List<MatchItem> matchItems = Arrays.asList(matchItem1, matchItem2);
// Mocking the service method
when(matchService.getMatchItems()).thenReturn(matchItems);
// Perform the GET request and verify the result
mockMvc.perform(MockMvcRequestBuilders.get("/match"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$[0].id").value(1))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].sport").value("Pools"))
.andExpect(MockMvcResultMatchers.jsonPath("$[1].id").value(2))
.andExpect(MockMvcResultMatchers.jsonPath("$[1].sport").value("Darts"));
}
@WithMockUser(username = "shy", password = "shy")
@Test
public void testGetMatchItemById() throws Exception {
// Prepare a specific match item
MatchItem matchItem = new MatchItem(1L, "Pools", 1L, 2L, LocalDateTime.now(), "pending", 0L, 0L, false, false, 0L);
// Mocking the service method
when(matchService.getMatchItemById(1L)).thenReturn(matchItem);
// Perform the GET request and verify the result
mockMvc.perform(MockMvcRequestBuilders.get("/match/1"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1))
.andExpect(MockMvcResultMatchers.jsonPath("$.sport").value("Pools"));
}
@WithMockUser(username = "shy", password = "shy")
@Test
public void testAddMatchItem() throws Exception {
// Prepare the match item to be added
MatchItem matchItem = new MatchItem(null, "Tennis", 1L, 2L, LocalDateTime.now(), "pending", 0L, 0L, false, false, 0L);
// Perform the POST request
mockMvc.perform(MockMvcRequestBuilders.post("/match")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"sport\":\"Tennis\",\"team1\":1,\"team2\":2,\"date\":\"" + LocalDateTime.now() + "\",\"status\":\"pending\",\"score1\":0,\"score2\":0,\"isLive\":false,\"isFinished\":false,\"duration\":0}"))
.andExpect(MockMvcResultMatchers.status().isOk());
}
@WithMockUser(username = "shy", password = "shy")
@Test
public void testUpdateMatchItem() throws Exception {
// Prepare the match item to be updated
MatchItem matchItem = new MatchItem(1L, "Pools", 1L, 2L, LocalDateTime.now(), "pending", 0L, 0L, false, false, 0L);
// Mocking the service method
when(matchService.getMatchItemById(1L)).thenReturn(matchItem);
// Perform the PUT request
mockMvc.perform(MockMvcRequestBuilders.put("/match/1")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"id\":1,\"sport\":\"Pools\",\"team1\":1,\"team2\":2,\"date\":\"" + LocalDateTime.now() + "\",\"status\":\"pending\",\"score1\":0,\"score2\":0,\"isLive\":false,\"isFinished\":false,\"duration\":0}"))
.andExpect(MockMvcResultMatchers.status().isOk());
}
@WithMockUser(username = "shy", password = "shy")
@Test
public void testDeleteMatchItem() throws Exception {
// Perform the DELETE request
mockMvc.perform(MockMvcRequestBuilders.delete("/match/1"))
.andExpect(MockMvcResultMatchers.status().isOk());
}
}
package uk.ac.cf.spring.demo;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
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.result.MockMvcResultMatchers.status;
//Full container Mock MVC Integration
@SpringBootTest
@AutoConfigureMockMvc
public class MatchControllerIngrationTest {
@MockBean
private MatchService matchService;
// @InjectMocks
// private MatchController matchController;
@Autowired
private MockMvc mockMvc;
// Integration Test with Mock MVC
@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(MockMvcRequestBuilders.get("/match"))
.andExpect(status().isOk());
verify(matchService, times(1)).getMatchItems();
}
// Integration Test with Mock MVC
@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(MockMvcRequestBuilders.get("/match/1"))
.andExpect(status().isOk());
verify(matchService, times(1)).getMatchItemById(1L);
}
//
}
package uk.ac.cf.spring.demo;
import org.junit.jupiter.api.Test;
import uk.ac.cf.spring.demo.sports.match.MatchItem;
import java.time.LocalDateTime;
public class TrueUnitTests {
// 测试MatchItem的getter和setter方法
@Test
public void testGettersAndSetters() {
// 创建一个 MatchItem 对象
MatchItem matchItem = new MatchItem();
// 测试 id 的 getter 和 setter
matchItem.setId(1L);
assert matchItem.getId() == 1L : "Test failed for id";
// 测试 sport 的 getter 和 setter
matchItem.setSport("football");
assert "football".equals(matchItem.getSport()) : "Test failed for sport";
// 测试 playerAId 的 getter 和 setter
matchItem.setPlayerAId(10L);
assert matchItem.getPlayerAId() == 10L : "Test failed for playerAId";
// 测试 playerBId 的 getter 和 setter
matchItem.setPlayerBId(20L);
assert matchItem.getPlayerBId() == 20L : "Test failed for playerBId";
// 测试 PlanTime 的 getter 和 setter
LocalDateTime now = LocalDateTime.now();
matchItem.setPlanTime(now);
assert now.equals(matchItem.getPlanTime()) : "Test failed for PlanTime";
// 测试 status 的 getter 和 setter
matchItem.setStatus("confirmed");
assert "confirmed".equals(matchItem.getStatus()) : "Test failed for status";
// 测试 scoreA 的 getter 和 setter
matchItem.setScoreA(5L);
assert matchItem.getScoreA() == 5L : "Test failed for scoreA";
// 测试 scoreB 的 getter 和 setter
matchItem.setScoreB(3L);
assert matchItem.getScoreB() == 3L : "Test failed for scoreB";
// 测试 confirmByA 的 getter 和 setter
matchItem.setConfirmByA(true);
assert matchItem.getConfirmByA() : "Test failed for confirmByA";
// 测试 confirmByB 的 getter 和 setter
matchItem.setConfirmByB(false);
assert !matchItem.getConfirmByB() : "Test failed for confirmByB";
// 测试 winnerId 的 getter 和 setter
matchItem.setWinnerId(10L);
assert matchItem.getWinnerId() == 10L : "Test failed for winnerId";
}
}
\ No newline at end of file
package uk.ac.cf.spring.demo.user.controller;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runner.RunWith;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit4.SpringRunner;
import io.github.bonigarcia.wdm.WebDriverManager;
import java.io.File;
import java.time.Duration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertTrue;
//@RunWith(SpringRunner.class)
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class DriverPageTests {
@Value("${local.server.port}")
private int port;
WebDriver webDriver;
// private WebDriverWait wait;
@BeforeAll
public static void setupClass() {
WebDriverManager.firefoxdriver().setup();
}
@BeforeEach
public void setupTest() {
// Get the current working directory
String currentDir = System.getProperty("user.dir");
// Set the path to the local geckodriver executable
System.setProperty("webdriver.gecko.driver", currentDir + File.separator + "geckodriver.exe");
FirefoxOptions options = new FirefoxOptions();
options.addArguments("--headless");
webDriver = new FirefoxDriver(options);
// wait = new WebDriverWait(webDriver, Duration.ofSeconds(10));
}
@AfterEach
public void teardown() {
if (webDriver != null) {
webDriver.quit();
}
}
@Test
public void testUserManagementPage() {
// Test fetching and displaying users
webDriver.get("http://localhost:" + port + "/html/backGroundUser.html");
// assertTrue(webDriver.findElement(By.cssSelector("#userTable")).isDisplayed());
// Test adding a new user
webDriver.findElement(By.id("username")).sendKeys("shy");
webDriver.findElement(By.id("email")).sendKeys("shy@creditsafe.com");
webDriver.findElement(By.id("password")).sendKeys("$2a$16$R0aSGzbklUhpRfIMhocewephgUDMFOffLb7faSwwHusqHh81G026i");
webDriver.findElement(By.id("role")).sendKeys("USER");
webDriver.findElement(By.xpath("//button[text()='Add User']")).click();
assertTrue(webDriver.findElement(By.cssSelector("#userTable")).getText().contains("shy"));
// Test editing a user
webDriver.findElement(By.xpath("//tr[td[text()='shy']]//button[text()='Edit']")).click();
webDriver.findElement(By.id("email")).clear();
webDriver.findElement(By.id("email")).sendKeys("upu@creditsafe.com");
webDriver.findElement(By.xpath("//button[text()='Update User']")).click();
assertTrue(webDriver.findElement(By.cssSelector("#userTable")).getText().contains("upu@creditsafe.com"));
// Test deleting a user
webDriver.findElement(By.xpath("//tr[td[text()='shy']]//button[text()='Delete']")).click();
assertThat(webDriver.findElement(By.cssSelector("#userTable")).getText()).doesNotContain("shy");
}
}
\ No newline at end of file
package uk.ac.cf.spring.demo.user.controller;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.http.ResponseEntity;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HTTPConnectionTest {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
public void testBackGroundUserPage() {
String url = "http://localhost:" + port + "/html/backGroundUser.html";
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
assertThat(response.getStatusCode().is2xxSuccessful()).isTrue();
assertThat(response.getBody()).contains("<title>User Management</title>");
}
}
package uk.ac.cf.spring.demo.user.controller;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
//import org.junit.runner.RunWith;
import org.junit.jupiter.api.extension.ExtendWith;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
//import org.openqa.selenium.chrome.ChromeDriver;
//import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
//import io.github.bonigarcia.wdm.WebDriverManager;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ExtendWith(SpringExtension.class)
@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class RegistrationAndLoginTest {
// @Value("${local.server.port}")
// private int port;
// an alternative really good resource: https://github.com/bonigarcia/webdrivermanager
@Autowired
private MockMvc mockMvc;
WebDriver webDriver;
@BeforeAll
static void setupClass() {
// set the path of geckodriver
System.setProperty("webdriver.gecko.driver", "C:\\UniProjects\\geckodriver-v0.35.0-win64\\geckodriver.exe");
}
// @BeforeAll
// static void setupClass() {
// WebDriverManager.firefoxdriver().setup();
// }
@BeforeEach
void setupTest() {
FirefoxOptions options = new FirefoxOptions();
// options.addArguments("--remote-debugging-port=42227");
options.addArguments("--headless");
webDriver = new FirefoxDriver(options);
}
@AfterEach
void teardown() {
// Close the browser after each test
if (webDriver != null) {
webDriver.quit();
}
}
@Test
public void testUserRegistrationAndLogin() throws Exception {
// Step 1: Navigate to the registration page
webDriver.get("http://localhost:8080/html/register.html");
// Fill out the registration form
webDriver.findElement(By.id("username")).sendKeys("testuser");
webDriver.findElement(By.id("email")).sendKeys("testuser@creditsafe.com");
webDriver.findElement(By.id("password")).sendKeys("password123");
webDriver.findElement(By.cssSelector("button[type='submit']")).click();
// Wait for the registration to complete and redirect to the login page
Thread.sleep(2000); // Simple wait for demonstration purposes
// Step 2: Navigate to the login page
webDriver.get("http://localhost:8080/html/login.html");
// Fill out the login form
webDriver.findElement(By.id("email")).sendKeys("testuser@creditsafe.com");
webDriver.findElement(By.id("password")).sendKeys("password123");
webDriver.findElement(By.cssSelector("button[type='submit']")).click();
// Wait for the login to complete and redirect to the match schedule page
Thread.sleep(2000); // Simple wait for demonstration purposes
// Verify that the user is redirected to the match schedule page
String currentUrl = webDriver.getCurrentUrl();
assert currentUrl.endsWith("/html/matchSchedule.html");
}
@Test
public void testLoginWithInvalidCredentials() throws Exception {
// Step 1: Navigate to the login page
webDriver.get("http://localhost:8080/html/login.html");
// Fill out the login form with invalid credentials
webDriver.findElement(By.id("email")).sendKeys("invalid@example.com");
webDriver.findElement(By.id("password")).sendKeys("wrongpassword");
webDriver.findElement(By.cssSelector("button[type='submit']")).click();
// Wait for the error message to appear
Thread.sleep(2000); // Simple wait for demonstration purposes
// Verify that the error message is displayed
String errorMessage = webDriver.findElement(By.id("message")).getText();
assert errorMessage.contains("Invalid email or password");
}
}
package uk.ac.cf.spring.demo.user.controller;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.boot.test.mock.mockito.MockBean;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import uk.ac.cf.spring.demo.user.*;
@SpringBootTest
@AutoConfigureMockMvc
//@WebMvcTest(RegistrationController.class)
public class RegistrationControllerMockMVCTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserRepository userRepository;
private ObjectMapper objectMapper;
@BeforeEach
public void setUp() {
MockitoAnnotations.openMocks(this);
objectMapper = new ObjectMapper(); // Initialize ObjectMapper
}
@Test
public void testShowRegistrationForm() throws Exception {
mockMvc.perform(get("/register"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(view().name("html/register.html"));
}
@Test
public void testRegisterUser_Success() throws Exception {
User user = new User(null, "dummy", "dummy@creditsafe.com", "password", "USER");
when(userRepository.existsByUsername(user.getUsername())).thenReturn(false);
when(userRepository.existsByEmail(user.getEmail())).thenReturn(false);
mockMvc.perform(post("/api/users/register")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(user)))
.andExpect(status().isOk())
.andExpect(content().json("{\"message\": \"Registration successful\"}"));
verify(userRepository, times(1)).save(user); // Verifying the save method is called once with the user object.
}
@Test
public void testRegisterUser_UsernameExists() throws Exception {
User user = new User(null, "dummy", "dummy@creditsafe.com", "password", "USER");
when(userRepository.existsByUsername(user.getUsername())).thenReturn(true);
mockMvc.perform(post("/api/users/register")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(user)))
.andExpect(status().isBadRequest())
.andExpect(content().json("{\"message\": \"Username already exists\"}"));
verify(userRepository, never()).save(user); // Verify that save is not called when username exists.
}
}
package uk.ac.cf.spring.demo.user.controller;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class RegistrationControllerTest {
@BeforeEach
void setUp() {
}
@AfterEach
void tearDown() {
}
@Test
void showRegistrationForm() {
}
@Test
void registerUser() {
}
}
\ No newline at end of file
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment