Skip to content

Commit

Permalink
Merge pull request #221 from Arquisoft/multiplayer-e2e-tests
Browse files Browse the repository at this point in the history
Some e2e tests for multiplayer (no accept)
  • Loading branch information
Pelayori authored Apr 27, 2024
2 parents 46ef70f + 6802453 commit 211b35a
Show file tree
Hide file tree
Showing 15 changed files with 253 additions and 51 deletions.
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

0 comments on commit 211b35a

Please sign in to comment.