Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some e2e tests for multiplayer #221

Merged
merged 8 commits into from
Apr 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<java.version>17</java.version>
<sonar.sources>src/main/java,src/test/resources/features</sonar.sources>
<sonar.jacoco.reportPaths>${project.basedir}/target/jacoco.exec</sonar.jacoco.reportPaths>
<sonar.exclusions>**/controllers/CustomErrorController.java, **/**/InsertSampleDataService.java</sonar.exclusions>
</properties>
<dependencies>
<dependency>
Expand Down
19 changes: 7 additions & 12 deletions src/main/java/com/uniovi/controllers/GameController.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,15 @@ public String getMultiplayerGame() {

@GetMapping("/multiplayerGame/{code}")
public String joinMultiplayerGame(@PathVariable String code, HttpSession session, Principal principal, Model model) {
if (!multiplayerSessionService.existsCode(code)) {
model.addAttribute("errorKey", "multi.code.invalid");
return "game/multiplayerGame";
}

Optional<Player> player = playerService.getUserByUsername(principal.getName());
Player p = player.orElse(null);
isMultiPlayer=true;
if(playerService.changeMultiplayerCode(p.getId(),code)){
if (playerService.changeMultiplayerCode(p.getId(),code)) {
multiplayerSessionService.addToLobby(code,p.getId());
model.addAttribute("multiplayerGameCode",code);
session.setAttribute("multiplayerCode",code);
Expand Down Expand Up @@ -153,6 +158,7 @@ public List<String> updatePlayerList(@PathVariable String code) {
Collections.sort(playerNames);
return playerNames;
}

@GetMapping("/game/lobby")
public String createLobby( HttpSession session, Model model) {
int code = Integer.parseInt((String)session.getAttribute("multiplayerCode"));
Expand Down Expand Up @@ -247,17 +253,6 @@ public String updateGame(Model model, HttpSession session, Principal principal)
return "game/fragments/gameFrame";
}

@GetMapping("/game/finished/{points}")
public String finishGame(@PathVariable int points, Model model, HttpSession session) {
GameSession gameSession = (GameSession) session.getAttribute(GAMESESSION_STR);
if (gameSession != null) {
gameSessionService.endGame(gameSession);
session.removeAttribute(GAMESESSION_STR);
}
model.addAttribute("score", points);
return "game/gameFinished";
}

@GetMapping("/game/points")
@ResponseBody
public String getPoints(HttpSession session) {
Expand Down
9 changes: 0 additions & 9 deletions src/main/java/com/uniovi/entities/Associations.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@
import java.util.*;

public class Associations {
private static final String UTILITY_CLASS = "Utility class";
private Associations() { throw new IllegalStateException(UTILITY_CLASS); }

public static class PlayerRole {
private PlayerRole() { throw new IllegalStateException(UTILITY_CLASS); }
/**
* Add a new association between a player and a role
*
Expand All @@ -32,7 +28,6 @@ public static void removeRole(Player player, Role role) {
}

public static class PlayerApiKey {
private PlayerApiKey() { throw new IllegalStateException(UTILITY_CLASS); }
/**
* Add a new association between a player and an API key
*
Expand All @@ -57,7 +52,6 @@ public static void removeApiKey(Player player, ApiKey apiKey) {
}

public static class ApiKeyAccessLog {
private ApiKeyAccessLog() { throw new IllegalStateException(UTILITY_CLASS); }
/**
* Add a new association between an API key and an access log
*
Expand All @@ -82,7 +76,6 @@ public static void removeAccessLog(ApiKey apiKey, RestApiAccessLog accessLog) {
}

public static class PlayerGameSession {
private PlayerGameSession() { throw new IllegalStateException(UTILITY_CLASS); }
/**
* Add a new association between a player and a game session
*
Expand All @@ -108,7 +101,6 @@ public static void removeGameSession(Player player, GameSession gameSession) {
}

public static class QuestionAnswers {
private QuestionAnswers() { throw new IllegalStateException(UTILITY_CLASS); }
/**
* Add a new association between a question and an answer
*
Expand Down Expand Up @@ -141,7 +133,6 @@ public static void removeAnswer(Question question, List<Answer> answer) {
}

public static class QuestionsCategory {
private QuestionsCategory() { throw new IllegalStateException(UTILITY_CLASS); }
/**
* Add a new association between a question and a category
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ public interface MultiplayerSessionService {
void addToLobby(String code, Long id);

void changeScore(String code,Long id,int score);

boolean existsCode(String code);
}
35 changes: 24 additions & 11 deletions src/main/java/com/uniovi/services/impl/MultiplayerSessionImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public Map<Player, Integer> getPlayersWithScores(int multiplayerCode) {
List<Player> sortedPlayers = playerScores.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
.toList();

Map<Player, Integer> playersSorted = new HashMap<>();
for (Player player : sortedPlayers) {
Expand All @@ -45,25 +45,38 @@ public Map<Player, Integer> getPlayersWithScores(int multiplayerCode) {

@Override
public void multiCreate(String code, Long id) {
Player p = playerRepository.findById(id).get();
multiplayerSessionRepository.save(new MultiplayerSession(code,p));
Player p = playerRepository.findById(id).orElse(null);

if (p != null)
multiplayerSessionRepository.save(new MultiplayerSession(code,p));
}

@Override
@Transactional
public void addToLobby(String code, Long id) {
Player p = playerRepository.findById(id).get();
MultiplayerSession ms=multiplayerSessionRepository.findByMultiplayerCode(code);
ms.addPlayer(p);
multiplayerSessionRepository.save(ms);
Player p = playerRepository.findById(id).orElse(null);

if (p != null) {
MultiplayerSession ms = multiplayerSessionRepository.findByMultiplayerCode(code);
ms.addPlayer(p);
multiplayerSessionRepository.save(ms);
}
}

@Override
@Transactional
public void changeScore(String code, Long id, int score) {
Player p = playerRepository.findById(id).get();
MultiplayerSession ms=multiplayerSessionRepository.findByMultiplayerCode(code);
ms.getPlayerScores().put(p,score);
multiplayerSessionRepository.save(ms);
Player p = playerRepository.findById(id).orElse(null);

if (p != null) {
MultiplayerSession ms = multiplayerSessionRepository.findByMultiplayerCode(code);
ms.getPlayerScores().put(p, score);
multiplayerSessionRepository.save(ms);
}
}

@Override
public boolean existsCode(String code) {
return multiplayerSessionRepository.findByMultiplayerCode(code) != null;
}
}
8 changes: 5 additions & 3 deletions src/main/java/com/uniovi/services/impl/PlayerServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,19 @@
import org.springframework.stereotype.Service;
import com.uniovi.entities.Role;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Random;

@Service
public class PlayerServiceImpl implements PlayerService {
private final PlayerRepository playerRepository;
private final RoleService roleService;
private final PasswordEncoder passwordEncoder;

private MultiplayerSessionService multiplayerSessionService;
private final MultiplayerSessionService multiplayerSessionService;
private final Random random = new SecureRandom();

public PlayerServiceImpl(PlayerRepository playerRepository, RoleService roleService, MultiplayerSessionService multiplayerSessionService,PasswordEncoder passwordEncoder) {
this.playerRepository = playerRepository;
Expand Down Expand Up @@ -190,7 +192,7 @@ public int createMultiplayerGame(Long id){
return -1;

Player p = player.get();
int code = (int)Math.floor(Math.random()*10000);
int code = random.nextInt(10000);
p.setMultiplayerCode(code);
playerRepository.save(p);
return code;
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ multi.results =Ver resultados
multi.finished= Partida finalizada
multi.points = Puntuaciones
multi.menu = Ir a la página de inicio
multi.code.invalid = Código de partida inválido
# -------------------Statements for the apiHome.html file---------------------
api.doc.title=Documentación de la API
api.doc.description=Esta es la documentación de la API de WIQ. Aquí puedes encontrar información sobre los recursos disponibles, los parámetros que aceptan y los ejemplos de uso.
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/messages_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ multi.results = See results
multi.finished= Finished game
multi.points = Points
multi.menu =Go to home page

multi.code.invalid = Invalid game code

# -------------------Statements for the apiHome.html file---------------------
api.doc.title=API Documentation
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/messages_es.properties
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ multi.results =Ver resultados
multi.finished= Partida finalizada
multi.points = Puntuaciones
multi.menu = Ir a la página de inicio

multi.code.invalid = Código de partida inválido

# -------------------Statements for the apiHome.html file---------------------
api.doc.title=Documentación de la API
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/messages_fr.properties
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ multi.results=Voir les résultats
multi.finished= Jeu terminé
multi.points = Points
multi.menu =aller à la page d'accueil

multi.code.invalid = Code invalide

# -------------------Statements for the apiHome.html file---------------------
api.doc.title=Documentation de l'API
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/templates/game/multiplayerGame.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<nav th:replace="~{fragments/nav}"></nav>

<div class="container" style="text-align: center">
<span class="alert alert-danger" th:if="${errorKey}" th:text="#{${errorKey}}"></span>
<label id="label-code" class="form-label col-sm-10 text-center mb-3" for="code" th:text="#{multi.label}"></label>
<div class="form-group col-sm-8 mx-auto">
<input type="text" class="form-control w-80 mx-auto" id="code" name="code"
Expand Down
114 changes: 111 additions & 3 deletions src/test/java/com/uniovi/Wiq_UnitTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,46 @@ public void testGetPlayersByEmails() throws IOException, InterruptedException, J
}
}

@Test
@Order(35)
public void testGetPlayersByEmailsAndRole() throws IOException, InterruptedException, JSONException {
Player player = playerService.getUsersByRole("ROLE_USER").get(0);
ApiKey apiKey = player.getApiKey();

HttpResponse<String> response = sendRequest("GET", "/api/players", Map.of(),
Map.of("apiKey", apiKey.getKeyToken(),
"emails", player.getEmail(), "role", "ROLE_USER"));

Assertions.assertEquals(200, response.statusCode());
JSONObject json = parseJsonResponse(response);
JSONArray players = json.getJSONArray("players");
Assertions.assertTrue(players.length() > 0);
for (int i = 0; i < players.length(); i++) {
JSONObject playerJson = players.getJSONObject(i);
Assertions.assertEquals(player.getEmail(), playerJson.getString("email"));
}
}

@Test
@Order(35)
public void testGetPlayersByRole() throws IOException, InterruptedException, JSONException {
Player player = playerService.getUsersByRole("ROLE_USER").get(0);
ApiKey apiKey = player.getApiKey();

HttpResponse<String> response = sendRequest("GET", "/api/players", Map.of(),
Map.of("apiKey", apiKey.getKeyToken(),
"role", "ROLE_USER"));

Assertions.assertEquals(200, response.statusCode());
JSONObject json = parseJsonResponse(response);
JSONArray players = json.getJSONArray("players");
Assertions.assertTrue(players.length() > 0);
for (int i = 0; i < players.length(); i++) {
JSONObject playerJson = players.getJSONObject(i);
Assertions.assertEquals(player.getEmail(), playerJson.getString("email"));
}
}

@Test
@Order(36)
public void testCreatePlayerEmptyApiKey() throws IOException, InterruptedException, JSONException {
Expand Down Expand Up @@ -796,14 +836,30 @@ public void testGetQuestions() throws IOException, InterruptedException, JSONExc
ApiKey apiKey = player.getApiKey();

HttpResponse<String> response = sendRequest("GET", "/api/questions", Map.of(),
Map.of("apiKey", apiKey.getKeyToken()));
Map.of("apiKey", apiKey.getKeyToken(), "lang", "es"));

Assertions.assertEquals(200, response.statusCode());
JSONObject json = parseJsonResponse(response);
Assertions.assertTrue(json.has("questions"));
Assertions.assertTrue(json.getJSONArray("questions").length() > 0);
}

@Test
@Order(50)
void testGetQuestionsInvalidId() throws IOException, InterruptedException, JSONException {
insertSomeQuestions();;
Player player = playerService.getUsersByRole("ROLE_USER").get(0);
ApiKey apiKey = player.getApiKey();

HttpResponse<String> response = sendRequest("GET", "/api/questions", Map.of(),
Map.of("apiKey", apiKey.getKeyToken(), "id", "notnumeric"));

Assertions.assertEquals(200, response.statusCode());
JSONObject json = parseJsonResponse(response);
Assertions.assertTrue(json.has("questions"));
Assertions.assertEquals(0, json.getJSONArray("questions").length());
}

@Test
@Order(51)
public void testGetQuestionsByCategoryName() throws IOException, InterruptedException, JSONException {
Expand Down Expand Up @@ -858,6 +914,25 @@ public void testGetQuestionById() throws IOException, InterruptedException, JSON
Assertions.assertEquals(question.getStatement(), questionJson.getString("statement"));
}

@Test
@Order(53)
public void testGetQuestionByStatement() throws IOException, InterruptedException, JSONException {
insertSomeQuestions();;
Player player = playerService.getUsersByRole("ROLE_USER").get(0);
ApiKey apiKey = player.getApiKey();
Question question = questionService.getAllQuestions().get(0);

HttpResponse<String> response = sendRequest("GET", "/api/questions", Map.of(),
Map.of("apiKey", apiKey.getKeyToken(),
"statement", question.getStatement()));

Assertions.assertEquals(200, response.statusCode());
JSONObject json = parseJsonResponse(response);
JSONObject questionJson = json.getJSONArray("questions").getJSONObject(0);
Assertions.assertEquals(question.getId(), questionJson.getLong("id"));
Assertions.assertEquals(question.getStatement(), questionJson.getString("statement"));
}

@Test
@Order(54)
void PlayerServiceImpl_addNewPlayer_UsedEmail() {
Expand Down Expand Up @@ -1364,9 +1439,8 @@ public void testModifyQuestionMissingData() throws IOException, InterruptedExcep

@Test
@Order(91)
@Tag("flaky")
public void testModifyQuestion() throws IOException, InterruptedException, JSONException {
insertSomeQuestions();;
insertSomeQuestions();
Question question = questionService.getAllQuestions().get(0);
Player player = playerService.getUsersByRole("ROLE_USER").get(0);
ApiKey apiKey = player.getApiKey();
Expand Down Expand Up @@ -1397,6 +1471,40 @@ public void testModifyQuestion() throws IOException, InterruptedException, JSONE
Assertions.assertEquals("Modified question", updatedQuestion.get().getStatement());
}

@Test
@Order(91)
public void testModifyQuestionNewCategory() throws IOException, InterruptedException, JSONException {
insertSomeQuestions();;
Question question = questionService.getAllQuestions().get(0);
Player player = playerService.getUsersByRole("ROLE_USER").get(0);
ApiKey apiKey = player.getApiKey();
Category category = categoryService.getCategoryByName("Geography");

Map<String, Object> data = new HashMap<>();
data.put("statement", "Modified question");

List<Map<String, Object>> opts = new ArrayList<>();
opts.add(Map.of("text", "Option A", "correct", true));
opts.add(Map.of("text", "Option B", "correct", false));
opts.add(Map.of("text", "Option C", "correct", false));
opts.add(Map.of("text", "Option D", "correct", false));

data.put("options", opts);
data.put("category", Map.of("name", "NewCreatedCategory"));
data.put("language", "en");

HttpResponse<String> response = sendRequest("PATCH", "/api/questions/" + question.getId(), Map.of("API-KEY", apiKey.getKeyToken()),
data);

Assertions.assertEquals(200, response.statusCode());
JSONObject json = parseJsonResponse(response);
Assertions.assertTrue(json.getBoolean("success"));

Optional<Question> updatedQuestion = questionService.getQuestion(question.getId());
Assertions.assertTrue(updatedQuestion.isPresent());
Assertions.assertEquals("Modified question", updatedQuestion.get().getStatement());
}

@Test
@Order(92)
public void testModifyQuestionWithLessOptions() throws IOException, InterruptedException, JSONException {
Expand Down
Loading
Loading