diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/Award.java b/src/main/java/cat/udl/eps/softarch/fll/domain/Award.java index 7f015ef1..f9886298 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/Award.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/Award.java @@ -50,6 +50,18 @@ public class Award extends UriEntity { @JsonIdentityReference(alwaysAsId = true) private Team winner; + public static Award create(String name, Edition edition, Team winner) { + DomainValidation.requireNonBlank(name, "name"); + DomainValidation.requireNonNull(edition, "edition"); + DomainValidation.requireNonNull(winner, "winner"); + + Award award = new Award(); + award.name = name; + award.edition = edition; + award.winner = winner; + return award; + } + @Override public Long getId() { return this.id; diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/Coach.java b/src/main/java/cat/udl/eps/softarch/fll/domain/Coach.java index e3fa2bb4..05aeac37 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/Coach.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/Coach.java @@ -1,7 +1,5 @@ package cat.udl.eps.softarch.fll.domain; -import java.util.HashSet; -import java.util.Set; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -13,6 +11,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; +import java.util.HashSet; +import java.util.Set; @Entity @Data @@ -30,11 +30,21 @@ public class Coach extends UriEntity { @NotBlank @Email @Column(unique = true) - private String emailAddress; + private String phoneNumber; @ManyToMany(mappedBy = "trainedBy") @ToString.Exclude private Set teams = new HashSet<>(); + + public static Coach create(String name, String emailAddress) { + DomainValidation.requireNonBlank(name, "name"); + DomainValidation.requireValidEmail(emailAddress, "emailAddress"); + + Coach coach = new Coach(); + coach.name = name; + coach.emailAddress = emailAddress; + return coach; + } } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/CompetitionTable.java b/src/main/java/cat/udl/eps/softarch/fll/domain/CompetitionTable.java index 45daab9c..68d944a9 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/CompetitionTable.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/CompetitionTable.java @@ -1,7 +1,5 @@ package cat.udl.eps.softarch.fll.domain; -import java.util.ArrayList; -import java.util.List; import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; @@ -11,32 +9,42 @@ import jakarta.validation.constraints.Size; import lombok.EqualsAndHashCode; import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; +import java.util.ArrayList; +import java.util.List; @Entity @Table(name = "competition_tables") -@Getter -@Setter -@NoArgsConstructor -@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true) public class CompetitionTable extends UriEntity { @Id @EqualsAndHashCode.Include private String id; - - @OneToMany(mappedBy = "competitionTable", cascade = {CascadeType.PERSIST, CascadeType.MERGE}) + @Getter + @OneToMany(mappedBy = "competitionTable", cascade = CascadeType.ALL) @JsonManagedReference("table-matches") - @Setter(lombok.AccessLevel.NONE) private List matches = new ArrayList<>(); - + @Getter @OneToMany(mappedBy = "supervisesTable") @Size(max = 3, message = "A table can have a maximum of 3 referees") @JsonManagedReference("table-referees") - @Setter(lombok.AccessLevel.NONE) private List referees = new ArrayList<>(); + public static CompetitionTable create(String id) { + DomainValidation.requireNonBlank(id, "id"); + CompetitionTable table = new CompetitionTable(); + table.id = id; + return table; + } + + @Override + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + public void setMatches(List matches) { new ArrayList<>(this.matches).forEach(this::removeMatch); if (matches != null) { @@ -44,6 +52,13 @@ public void setMatches(List matches) { } } + public void setReferees(List referees) { + new ArrayList<>(this.referees).forEach(this::removeReferee); + if (referees != null) { + referees.forEach(this::addReferee); + } + } + public void addMatch(Match match) { if (match == null) { return; @@ -55,10 +70,11 @@ public void addMatch(Match match) { CompetitionTable previousTable = match.getCompetitionTable(); if (previousTable != null && previousTable != this) { - previousTable.getMatches().removeIf(m -> m == match); + previousTable.removeMatch(match); + } + if (!matches.contains(match)) { + matches.add(match); } - - this.matches.add(match); match.setCompetitionTable(this); } @@ -67,18 +83,8 @@ public void removeMatch(Match match) { return; } - if (this.matches.removeIf(m -> m == match)) { - match.setCompetitionTable(null); - } - } - - public void setReferees(List referees) { - if (referees == this.referees) { - return; - } - List incoming = (referees == null) ? List.of() : new ArrayList<>(referees); - new ArrayList<>(this.referees).forEach(this::removeReferee); - incoming.forEach(this::addReferee); + matches.remove(match); + match.setCompetitionTable(null); } public void addReferee(Referee referee) { @@ -96,10 +102,12 @@ public void addReferee(Referee referee) { CompetitionTable previousTable = referee.getSupervisesTable(); if (previousTable != null && previousTable != this) { - previousTable.getReferees().removeIf(r -> r == referee); + previousTable.removeReferee(referee); } - - this.referees.add(referee); + if (referees.contains(referee)) { + return; + } + referees.add(referee); referee.setSupervisesTable(this); } @@ -108,8 +116,7 @@ public void removeReferee(Referee referee) { return; } - if (this.referees.removeIf(r -> r == referee)) { - referee.setSupervisesTable(null); - } + referees.remove(referee); + referee.setSupervisesTable(null); } } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/DomainValidation.java b/src/main/java/cat/udl/eps/softarch/fll/domain/DomainValidation.java new file mode 100644 index 00000000..e38e1db5 --- /dev/null +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/DomainValidation.java @@ -0,0 +1,83 @@ +package cat.udl.eps.softarch.fll.domain; + +import java.time.LocalDate; +import java.util.regex.Pattern; + +public final class DomainValidation { + + private static final Pattern EMAIL_PATTERN = + Pattern.compile("^[\\w\\-.]+@([\\w-]+\\.)+[\\w-]{2,}$"); + + private DomainValidation() { + } + + public static void requireNonBlank(String value, String fieldName) { + if (value == null) { + throw new DomainValidationException(fieldName + " must not be null"); + } + if (value.isBlank()) { + throw new DomainValidationException(fieldName + " must not be blank"); + } + } + + public static void requireValidEmail(String email, String fieldName) { + requireNonBlank(email, fieldName); + if (!EMAIL_PATTERN.matcher(email).matches()) { + throw new DomainValidationException(fieldName + " must be a valid email address"); + } + } + + public static void requireNonNegative(Integer value, String fieldName) { + if (value == null) { + throw new DomainValidationException(fieldName + " must not be null"); + } + if (value < 0) { + throw new DomainValidationException(fieldName + " must not be negative"); + } + } + + public static void requireMin(Integer value, Integer minValue, String fieldName) { + if (value == null) { + throw new DomainValidationException(fieldName + " must not be null"); + } + if (value < minValue) { + throw new DomainValidationException(fieldName + " must not be less than " + minValue); + } + } + + public static void requirePast(LocalDate value, String fieldName) { + if (value == null) { + throw new DomainValidationException(fieldName + " must not be null"); + } + if (!value.isBefore(LocalDate.now())) { + throw new DomainValidationException(fieldName + " must be in the past"); + } + } + + public static void requireLengthBetween(String value, Integer minLength, Integer maxLength, String fieldName) { + if (value == null) { + throw new DomainValidationException(fieldName + " must not be null"); + } + if (value.length() < minLength) { + throw new DomainValidationException(fieldName + " length must not be less than " + minLength); + } + if (value.length() > maxLength) { + throw new DomainValidationException(fieldName + " length must not be more than " + maxLength); + } + } + + public static void requireMaxLength(String value, Integer maxLength, String fieldName) { + if (value == null) { + throw new DomainValidationException(fieldName + " must not be null"); + } + if (value.length() > maxLength) { + throw new DomainValidationException(fieldName + " length must not be more than " + maxLength); + } + } + + public static void requireNonNull(Object value, String fieldName) { + if (value == null) { + throw new DomainValidationException(fieldName + " must not be null"); + } + } +} diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/DomainValidationException.java b/src/main/java/cat/udl/eps/softarch/fll/domain/DomainValidationException.java new file mode 100644 index 00000000..49a440a6 --- /dev/null +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/DomainValidationException.java @@ -0,0 +1,8 @@ +package cat.udl.eps.softarch.fll.domain; + +public class DomainValidationException extends RuntimeException { + + public DomainValidationException(String message) { + super(message); + } +} diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/Edition.java b/src/main/java/cat/udl/eps/softarch/fll/domain/Edition.java index c5d90914..8c8f8e09 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/Edition.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/Edition.java @@ -1,7 +1,5 @@ package cat.udl.eps.softarch.fll.domain; -import java.util.HashSet; -import java.util.Set; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; @@ -18,6 +16,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; +import java.util.HashSet; +import java.util.Set; @Entity @Data @@ -48,13 +48,28 @@ public class Edition extends UriEntity { @ManyToMany @JoinTable( - name = "edition_teams", - joinColumns = @JoinColumn(name = "edition_id"), - inverseJoinColumns = @JoinColumn(name = "team_name")) + name = "edition_teams", + joinColumns = @JoinColumn(name = "edition_id"), + inverseJoinColumns = @JoinColumn(name = "team_name")) @ToString.Exclude @EqualsAndHashCode.Exclude private Set teams = new HashSet<>(); + protected Edition() { + } + + public static Edition create(Integer year, String venueName, String description) { + DomainValidation.requireNonNull(year, "year"); + DomainValidation.requireNonBlank(venueName, "venueName"); + DomainValidation.requireNonBlank(description, "description"); + + Edition edition = new Edition(); + edition.year = year; + edition.venueName = venueName; + edition.description = description; + return edition; + } + public boolean hasReachedMaxTeams() { return teams.size() >= MAX_TEAMS; } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/Floater.java b/src/main/java/cat/udl/eps/softarch/fll/domain/Floater.java index 49928cf0..98043ded 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/Floater.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/Floater.java @@ -1,25 +1,27 @@ package cat.udl.eps.softarch.fll.domain; -import java.util.HashSet; -import java.util.Set; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.ManyToMany; import jakarta.persistence.Table; import jakarta.validation.constraints.NotBlank; +import lombok.AccessLevel; import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; +import java.util.HashSet; +import java.util.Set; @Entity @Table(name = "floaters") @Getter @Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) @EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) public class Floater extends Volunteer { - @NotBlank(message = "Student code is mandatory") @Column(unique = true) private String studentCode; @@ -27,5 +29,14 @@ public class Floater extends Volunteer { @ManyToMany(mappedBy = "floaters") @ToString.Exclude private Set assistedTeams = new HashSet<>(); + + public static Floater create(String name, String emailAddress, String phoneNumber, String studentCode) { + DomainValidation.requireNonBlank(studentCode, "studentCode"); + + Floater floater = new Floater(); + floater.initFields(name, emailAddress, phoneNumber); + floater.studentCode = studentCode; + return floater; + } } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/Judge.java b/src/main/java/cat/udl/eps/softarch/fll/domain/Judge.java index a14ad8ab..d426dde6 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/Judge.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/Judge.java @@ -6,7 +6,9 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; +import lombok.AccessLevel; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; @@ -14,6 +16,7 @@ @Table(name = "judge") @Getter @Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class Judge extends Volunteer { @Column(name = "is_expert") @@ -23,4 +26,10 @@ public class Judge extends Volunteer { @JoinColumn(name = "member_of_room") private ProjectRoom memberOfRoom; + public static Judge create(String name, String emailAddress, String phoneNumber) { + Judge judge = new Judge(); + judge.initFields(name, emailAddress, phoneNumber); + return judge; + } + } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/Match.java b/src/main/java/cat/udl/eps/softarch/fll/domain/Match.java index 184eb28a..2ddf9776 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/Match.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/Match.java @@ -1,6 +1,5 @@ package cat.udl.eps.softarch.fll.domain; -import java.time.LocalTime; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonIdentityReference; import jakarta.persistence.Entity; @@ -15,14 +14,11 @@ import jakarta.persistence.Table; import lombok.EqualsAndHashCode; import lombok.Getter; -import lombok.Setter; -import lombok.NoArgsConstructor; +import java.time.LocalTime; @Entity @Table(name = "matches") @Getter -@Setter -@NoArgsConstructor @EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true) public class Match extends UriEntity { @@ -31,33 +27,87 @@ public class Match extends UriEntity { @EqualsAndHashCode.Include private Long id; + @Getter private LocalTime startTime; + + @Getter private LocalTime endTime; - @Enumerated(EnumType.STRING) - private MatchState state = MatchState.SCHEDULED; + @Getter + @JsonBackReference("round-matches") + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "round_id") + private Round round; + @Getter + @JsonBackReference("table-matches") @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "referee_id") - private Referee referee; + @JoinColumn(name = "table_id") + private CompetitionTable competitionTable; + @Getter @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "team_a_id") @JsonIdentityReference(alwaysAsId = true) private Team teamA; + @Getter @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "team_b_id") @JsonIdentityReference(alwaysAsId = true) private Team teamB; + @Getter @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "round_id") - @JsonBackReference("round-matches") - private Round round; + @JoinColumn(name = "referee_id") + private Referee referee; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "table_id") - @JsonBackReference("table-matches") - private CompetitionTable competitionTable; + @Getter + @Enumerated(EnumType.STRING) + private MatchState state = MatchState.SCHEDULED; + + public Match() { + // Doesn't need to restrict values + } + + @Override + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public void setStartTime(LocalTime startTime) { + this.startTime = startTime; + } + + public void setEndTime(LocalTime endTime) { + this.endTime = endTime; + } + + public void setRound(Round round) { + this.round = round; + } + + public void setCompetitionTable(CompetitionTable competitionTable) { + this.competitionTable = competitionTable; + } + + public void setTeamA(Team teamA) { + this.teamA = teamA; + } + + public void setTeamB(Team teamB) { + this.teamB = teamB; + } + + public void setReferee(Referee referee) { + this.referee = referee; + } + + public void setState(MatchState state) { + this.state = state; + } } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/MatchResult.java b/src/main/java/cat/udl/eps/softarch/fll/domain/MatchResult.java index 030fa7ff..3838940e 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/MatchResult.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/MatchResult.java @@ -26,25 +26,35 @@ public class MatchResult extends UriEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - /** - * The score obtained by the team in this match. Must be a non-negative integer. - */ @NotNull(message = "Score is mandatory") @Min(value = 0, message = "Score cannot be negative") private Integer score; - - @Override - public Long getId() { - return this.id; - } - @NotNull @ManyToOne @JsonIdentityReference(alwaysAsId = true) private Match match; - @NotNull @ManyToOne @JsonIdentityReference(alwaysAsId = true) private Team team; + + protected MatchResult() { + } + + public static MatchResult create(Integer score, Match match, Team team) { + DomainValidation.requireNonNegative(score, "score"); + DomainValidation.requireNonNull(match, "match"); + DomainValidation.requireNonNull(team, "team"); + + MatchResult result = new MatchResult(); + result.score = score; + result.match = match; + result.team = team; + return result; + } + + @Override + public Long getId() { + return this.id; + } } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/MediaContent.java b/src/main/java/cat/udl/eps/softarch/fll/domain/MediaContent.java index ee7cdb56..e03a2822 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/MediaContent.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/MediaContent.java @@ -1,6 +1,5 @@ package cat.udl.eps.softarch.fll.domain; -import org.jspecify.annotations.Nullable; import com.fasterxml.jackson.annotation.JsonIdentityReference; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -9,6 +8,7 @@ import jakarta.validation.constraints.NotBlank; import lombok.Data; import lombok.EqualsAndHashCode; +import org.jspecify.annotations.Nullable; @Entity @Data @@ -27,6 +27,19 @@ public class MediaContent extends UriEntity { @JsonIdentityReference(alwaysAsId = true) private Edition edition; + protected MediaContent() { + } + + public static MediaContent create(String url, String type) { + DomainValidation.requireNonBlank(url, "url"); + DomainValidation.requireNonBlank(type, "type"); + + MediaContent content = new MediaContent(); + content.url = url; + content.type = type; + return content; + } + @Override public @Nullable String getId() { return url; diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/Record.java b/src/main/java/cat/udl/eps/softarch/fll/domain/Record.java index ffced16d..a008c71e 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/Record.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/Record.java @@ -1,7 +1,5 @@ package cat.udl.eps.softarch.fll.domain; -import java.time.ZonedDateTime; -import org.springframework.format.annotation.DateTimeFormat; import com.fasterxml.jackson.annotation.JsonIdentityReference; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -11,6 +9,8 @@ import jakarta.validation.constraints.NotBlank; import lombok.Data; import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.ZonedDateTime; @Entity @Data @@ -36,4 +36,11 @@ public class Record extends UriEntity { @JsonIdentityReference(alwaysAsId = true) private User owner; + public static Record create(String name) { + DomainValidation.requireNonBlank(name, "name"); + + Record newRecord = new Record(); + newRecord.name = name; + return newRecord; + } } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/Referee.java b/src/main/java/cat/udl/eps/softarch/fll/domain/Referee.java index de9cf127..4f4c10d6 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/Referee.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/Referee.java @@ -6,24 +6,40 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; -import lombok.EqualsAndHashCode; -import lombok.Getter; +import lombok.AccessLevel; import lombok.NoArgsConstructor; -import lombok.Setter; @Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) @Table(name = "referees") -@Getter -@Setter -@NoArgsConstructor -@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) public class Referee extends Volunteer { private boolean expert; - @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "supervises_table_id") @JsonBackReference("table-referees") private CompetitionTable supervisesTable; + + public static Referee create(String name, String emailAddress, String phoneNumber) { + Referee referee = new Referee(); + referee.initFields(name, emailAddress, phoneNumber); + return referee; + } + + public boolean isExpert() { + return expert; + } + + public void setExpert(boolean expert) { + this.expert = expert; + } + + public CompetitionTable getSupervisesTable() { + return supervisesTable; + } + + public void setSupervisesTable(CompetitionTable supervisesTable) { + this.supervisesTable = supervisesTable; + } } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/Round.java b/src/main/java/cat/udl/eps/softarch/fll/domain/Round.java index 24b6b733..55098482 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/Round.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/Round.java @@ -1,14 +1,12 @@ package cat.udl.eps.softarch.fll.domain; -import java.util.ArrayList; -import java.util.List; import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; -import jakarta.persistence.FetchType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; @@ -16,8 +14,10 @@ import jakarta.persistence.Table; import lombok.EqualsAndHashCode; import lombok.Getter; -import lombok.Setter; import lombok.NoArgsConstructor; +import lombok.Setter; +import java.util.ArrayList; +import java.util.List; @Entity @Table(name = "rounds") @@ -77,7 +77,7 @@ public void removeMatch(Match match) { return; } - if (this.matches.removeIf(m -> m == match)) { + if (matches.removeIf(m -> m == match)) { match.setRound(null); } } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/ScientificProject.java b/src/main/java/cat/udl/eps/softarch/fll/domain/ScientificProject.java index 4126b50c..98fda081 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/ScientificProject.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/ScientificProject.java @@ -27,17 +27,23 @@ public class ScientificProject extends UriEntity { private Integer score; private String comments; - @NotNull @ManyToOne @JoinColumn(name = "team_name", nullable = false) @JsonIdentityReference(alwaysAsId = true) private Team team; - @NotNull @ManyToOne @JoinColumn(name = "edition_id", nullable = false) @JsonIdentityReference(alwaysAsId = true) private Edition edition; + + public static ScientificProject create(Integer score) { + DomainValidation.requireNonNegative(score, "score"); + + ScientificProject project = new ScientificProject(); + project.score = score; + return project; + } } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/Team.java b/src/main/java/cat/udl/eps/softarch/fll/domain/Team.java index 07198341..8c646f9e 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/Team.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/Team.java @@ -1,10 +1,6 @@ package cat.udl.eps.softarch.fll.domain; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import com.fasterxml.jackson.annotation.JsonIdentityReference; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -20,62 +16,94 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.PastOrPresent; import jakarta.validation.constraints.Size; -import com.fasterxml.jackson.annotation.JsonIdentityReference; -import lombok.AllArgsConstructor; +import lombok.AccessLevel; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; @Entity @Getter @Setter -@NoArgsConstructor -@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) @EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false) @ToString @Table(name = "team") public class Team extends UriEntity { - @Override - public String getId() { - return name; - } - @Id @EqualsAndHashCode.Include @NotBlank(message = "Name is mandatory") @Size(min = 3, max = 50, message = "Name must be between 3 and 50 characters") @Column(name = "name", length = 50) private String name; - @NotBlank(message = "City is mandatory") @Size(max = 100, message = "City name too long") @Column(name = "city", length = 100) private String city; - @NotNull(message = "Foundation year is mandatory") @Min(value = 1998, message = "Foundation year must be 1998 or later") private Integer foundationYear; - @Size(max = 100, message = "Educational center name too long") private String educationalCenter; - @NotBlank(message = "Category is mandatory") private String category; - @PastOrPresent(message = "Inscription date cannot be in the future") @Column(nullable = false) private LocalDate inscriptionDate; - @OneToMany(mappedBy = "team", cascade = CascadeType.ALL, orphanRemoval = true) @Size(max = 10, message = "A team cannot have more than 10 members") @ToString.Exclude private List members = new ArrayList<>(); + @ManyToMany + @JoinTable( + name = "team_edition", + joinColumns = @JoinColumn(name = "team_name", referencedColumnName = "name"), + inverseJoinColumns = @JoinColumn(name = "edition_id")) + @JsonIdentityReference(alwaysAsId = true) + @ToString.Exclude + private Set registeredEditions = new HashSet<>(); + @ManyToMany + @JoinTable( + name = "team_coach", + joinColumns = @JoinColumn(name = "team_name"), + inverseJoinColumns = @JoinColumn(name = "coach_id")) + @ToString.Exclude + private Set trainedBy = new HashSet<>(); + @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) + @JoinTable( + name = "team_floaters", + joinColumns = @JoinColumn(name = "team_name"), + inverseJoinColumns = @JoinColumn(name = "floater_id")) + @ToString.Exclude + private Set floaters = new HashSet<>(); - public Team(String name) { - this.name = name; + public static Team create(String name, String city, Integer foundationYear, String category) { + DomainValidation.requireNonBlank(name, "name"); + DomainValidation.requireLengthBetween(name, 3, 50, "name"); + DomainValidation.requireNonBlank(city, "city"); + DomainValidation.requireLengthBetween(city, 1, 100, "city"); + DomainValidation.requireMin(foundationYear, 1998, "foundationYear"); + DomainValidation.requireNonBlank(category, "category"); + + Team team = new Team(); + team.name = name; + team.city = city; + team.foundationYear = foundationYear; + team.category = category; + team.inscriptionDate = LocalDate.now(); + return team; + } + + @Override + public String getId() { + return name; } @PrePersist @@ -93,33 +121,6 @@ public void addMember(TeamMember member) { member.setTeam(this); } - @ManyToMany - @JoinTable( - name = "team_edition", - joinColumns = @JoinColumn(name = "team_name", referencedColumnName = "name"), - inverseJoinColumns = @JoinColumn(name = "edition_id")) - @JsonIdentityReference(alwaysAsId = true) - @ToString.Exclude - private Set registeredEditions = new HashSet<>(); - - @ManyToMany - @JoinTable( - name = "team_coach", - joinColumns = @JoinColumn(name = "team_name"), - inverseJoinColumns = @JoinColumn(name = "coach_id")) - @ToString.Exclude - private Set trainedBy = new HashSet<>(); - - @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) - @JoinTable( - name = "team_floaters", - joinColumns = @JoinColumn(name = "team_name"), - inverseJoinColumns = @JoinColumn(name = "floater_id")) - @ToString.Exclude - private Set floaters = new HashSet<>(); - - - public void addFloater(Floater floater) { if (floaters.contains(floater)) { return; diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/TeamMember.java b/src/main/java/cat/udl/eps/softarch/fll/domain/TeamMember.java index b67dd9f5..8b2df798 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/TeamMember.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/TeamMember.java @@ -1,6 +1,5 @@ package cat.udl.eps.softarch.fll.domain; -import java.time.LocalDate; import com.fasterxml.jackson.annotation.JsonIdentityReference; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -15,53 +14,63 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Past; import jakarta.validation.constraints.Size; -import lombok.AllArgsConstructor; +import lombok.AccessLevel; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import java.time.LocalDate; @Entity @Getter @Setter -@NoArgsConstructor -@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) @EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false) @Table(name = "team_member") public class TeamMember extends UriEntity { - @Override - public Long getId() { - return id; - } - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @EqualsAndHashCode.Include private Long id; - @NotBlank(message = "Member name is mandatory") @Size(min = 2, max = 100, message = "Name must be between 2 and 100 characters") private String name; - @NotNull(message = "Birth date cannot be null") @Past(message = "Birth date must be in the past") private LocalDate birthDate; - @Size(max = 20, message = "Gender too long") private String gender; - @Size(max = 10, message = "T-shirt size too long") private String tShirtSize; - @NotBlank(message = "Role is mandatory") @Size(max = 50, message = "Role name too long") @Column(length = 50) private String role; - @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "team_name", nullable = false) @NotNull(message = "A member must belong to a team") @JsonIdentityReference(alwaysAsId = true) private Team team; + + public static TeamMember create(String name, String role, LocalDate birthDate, Team team) { + DomainValidation.requireNonBlank(name, "name"); + DomainValidation.requireLengthBetween(name, 2, 100, "name"); + DomainValidation.requireNonBlank(role, "role"); + DomainValidation.requireMaxLength(role, 50, "role"); + DomainValidation.requirePast(birthDate, "birthDate"); + DomainValidation.requireNonNull(team, "team"); + + TeamMember member = new TeamMember(); + member.name = name; + member.role = role; + member.birthDate = birthDate; + team.addMember(member); + return member; + } + + @Override + public Long getId() { + return id; + } } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/User.java b/src/main/java/cat/udl/eps/softarch/fll/domain/User.java index e3cb15ea..6906be68 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/User.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/User.java @@ -1,12 +1,5 @@ package cat.udl.eps.softarch.fll.domain; -import java.util.Collection; -import org.hibernate.validator.constraints.Length; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; import jakarta.persistence.Column; @@ -17,6 +10,13 @@ import jakarta.validation.constraints.NotBlank; import lombok.Data; import lombok.EqualsAndHashCode; +import org.hibernate.validator.constraints.Length; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import java.util.Collection; @Entity @Table(name = "users") // Avoid collision with system table "user" @@ -25,23 +25,32 @@ public class User extends UriEntity implements UserDetails { public static final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); - @Id private String id; - @NotBlank @Email @Column(unique = true) private String email; - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) @NotBlank @Length(min = 8, max = 256) private String password; - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private boolean passwordReset; + public static User create(String id, String email, String password) { + DomainValidation.requireNonBlank(id, "id"); + DomainValidation.requireValidEmail(email, "email"); + DomainValidation.requireNonBlank(password, "password"); + DomainValidation.requireLengthBetween(password, 8, 256, "password"); + + User user = new User(); + user.id = id; + user.email = email; + user.password = passwordEncoder.encode(password); + return user; + } + public void encodePassword() { this.password = passwordEncoder.encode(this.password); } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/Venue.java b/src/main/java/cat/udl/eps/softarch/fll/domain/Venue.java index faffa820..cedbae28 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/Venue.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/Venue.java @@ -7,14 +7,17 @@ import jakarta.persistence.Id; import jakarta.persistence.Table; import jakarta.validation.constraints.NotBlank; +import lombok.AccessLevel; import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; @Entity @Table(name = "venue") @Getter @Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) @EqualsAndHashCode(onlyExplicitlyIncluded = true) public class Venue { @@ -30,4 +33,14 @@ public class Venue { @NotBlank @Column(name = "city", nullable = false) private String city; + + public static Venue create(String name, String city) { + DomainValidation.requireNonBlank(name, "name"); + DomainValidation.requireNonBlank(city, "city"); + + Venue venue = new Venue(); + venue.name = name; + venue.city = city; + return venue; + } } diff --git a/src/main/java/cat/udl/eps/softarch/fll/domain/Volunteer.java b/src/main/java/cat/udl/eps/softarch/fll/domain/Volunteer.java index 7fa1a31c..2025238b 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/domain/Volunteer.java +++ b/src/main/java/cat/udl/eps/softarch/fll/domain/Volunteer.java @@ -21,10 +21,10 @@ @Table(name = "volunteers") @Inheritance(strategy = InheritanceType.JOINED) @Getter -@Setter @EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false) public abstract class Volunteer extends UriEntity { + @Setter @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @EqualsAndHashCode.Include @@ -40,9 +40,31 @@ public abstract class Volunteer extends UriEntity { @NotBlank(message = "Phone number is mandatory") private String phoneNumber; - + @Setter @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "edition_id") private Edition edition; + + protected Volunteer() { + } + + public void setPhoneNumber(String phoneNumber) { + DomainValidation.requireNonBlank(phoneNumber, "phoneNumber"); + this.phoneNumber = phoneNumber; + } + + protected void validateFields(String name, String emailAddress, String phoneNumber) { + DomainValidation.requireNonBlank(name, "name"); + DomainValidation.requireValidEmail(emailAddress, "emailAddress"); + DomainValidation.requireNonBlank(phoneNumber, "phoneNumber"); + } + + protected void initFields(String name, String emailAddress, String phoneNumber) { + validateFields(name, emailAddress, phoneNumber); + + this.name = name; + this.emailAddress = emailAddress; + this.phoneNumber = phoneNumber; + } } diff --git a/src/main/java/cat/udl/eps/softarch/fll/service/MatchScoreRegistrationService.java b/src/main/java/cat/udl/eps/softarch/fll/service/MatchScoreRegistrationService.java index 6068c95b..6ce6a698 100644 --- a/src/main/java/cat/udl/eps/softarch/fll/service/MatchScoreRegistrationService.java +++ b/src/main/java/cat/udl/eps/softarch/fll/service/MatchScoreRegistrationService.java @@ -1,16 +1,16 @@ package cat.udl.eps.softarch.fll.service; -import java.util.List; -import java.util.Map; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import cat.udl.eps.softarch.fll.domain.Match; import cat.udl.eps.softarch.fll.domain.MatchResult; import cat.udl.eps.softarch.fll.domain.Team; import cat.udl.eps.softarch.fll.repository.MatchRepository; import cat.udl.eps.softarch.fll.repository.MatchResultRepository; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.Map; @Service public class MatchScoreRegistrationService { @@ -19,9 +19,11 @@ public class MatchScoreRegistrationService { private final MatchResultRepository matchResultRepository; private final RankingService rankingService; - public MatchScoreRegistrationService(MatchRepository matchRepository, - MatchResultRepository matchResultRepository, - RankingService rankingService) { + public MatchScoreRegistrationService( + MatchRepository matchRepository, + MatchResultRepository matchResultRepository, + RankingService rankingService + ) { this.matchRepository = matchRepository; this.matchResultRepository = matchResultRepository; this.rankingService = rankingService; @@ -32,37 +34,37 @@ public void registerMatchScore(Long matchId, String teamAId, String teamBId, Int validateRequestShape(matchId, teamAId, teamBId, teamAScore, teamBScore); Match match = matchRepository.findById(matchId) - .orElseThrow(() -> new RegistrationException( - ErrorCode.MATCH_NOT_FOUND, - "Match with id " + matchId + " does not exist")); + .orElseThrow(() -> new RegistrationException( + ErrorCode.MATCH_NOT_FOUND, + "Match with id " + matchId + " does not exist")); validateMatchState(match); if (matchResultRepository.existsByMatch(match)) { throw new RegistrationException( - ErrorCode.RESULT_ALREADY_EXISTS, - "A result has already been registered for this match"); + ErrorCode.RESULT_ALREADY_EXISTS, + "A result has already been registered for this match"); } validateScoreValues(teamAId, teamBId, teamAScore, teamBScore); Map scoreByTeam = Map.of( - teamAId, teamAScore, - teamBId, teamBScore); + teamAId, teamAScore, + teamBId, teamBScore); Team matchTeamA = match.getTeamA(); Team matchTeamB = match.getTeamB(); validateTeamAssignment(matchTeamA, matchTeamB, teamAId, teamBId); List matchResults = List.of( - buildMatchResult(match, matchTeamA, scoreByTeam.get(matchTeamA.getId())), - buildMatchResult(match, matchTeamB, scoreByTeam.get(matchTeamB.getId()))); + buildMatchResult(match, matchTeamA, scoreByTeam.get(matchTeamA.getId())), + buildMatchResult(match, matchTeamB, scoreByTeam.get(matchTeamB.getId()))); try { matchResultRepository.saveAllAndFlush(matchResults); } catch (DataIntegrityViolationException exception) { throw new RegistrationException( - ErrorCode.RESULT_ALREADY_EXISTS, - "A result has already been registered for this match"); + ErrorCode.RESULT_ALREADY_EXISTS, + "A result has already been registered for this match"); } rankingService.recalculateRanking(); } @@ -70,84 +72,63 @@ public void registerMatchScore(Long matchId, String teamAId, String teamBId, Int private void validateRequestShape(Long matchId, String teamAId, String teamBId, Integer teamAScore, Integer teamBScore) { if (matchId == null || teamAId == null || teamBId == null || teamAScore == null || teamBScore == null) { throw new RegistrationException( - ErrorCode.INVALID_SCORE_PAYLOAD, - "Invalid score payload"); + ErrorCode.INVALID_SCORE_PAYLOAD, + "Invalid score payload"); } } private void validateMatchState(Match match) { if (match.getStartTime() == null) { throw new RegistrationException( - ErrorCode.INVALID_MATCH_STATE, - "Match is not in a valid state for result submission"); + ErrorCode.INVALID_MATCH_STATE, + "Match is not in a valid state for result submission"); } if (match.getEndTime() == null) { throw new RegistrationException( - ErrorCode.MATCH_NOT_FINISHED, - "Match must be finished before registering the result"); + ErrorCode.MATCH_NOT_FINISHED, + "Match must be finished before registering the result"); } if (match.getEndTime().isBefore(match.getStartTime())) { throw new RegistrationException( - ErrorCode.INVALID_MATCH_STATE, - "Match end time cannot be before start time"); + ErrorCode.INVALID_MATCH_STATE, + "Match end time cannot be before start time"); } } private void validateScoreValues(String teamAId, String teamBId, Integer teamAScore, Integer teamBScore) { if (teamAId.equals(teamBId)) { throw new RegistrationException( - ErrorCode.INVALID_SCORE, - "A match result requires two different teams"); + ErrorCode.INVALID_SCORE, + "A match result requires two different teams"); } if (teamAScore < 0 || teamBScore < 0) { throw new RegistrationException( - ErrorCode.INVALID_SCORE, - "Score cannot be negative"); + ErrorCode.INVALID_SCORE, + "Score cannot be negative"); } } private void validateTeamAssignment(Team matchTeamA, Team matchTeamB, String providedTeamA, String providedTeamB) { if (matchTeamA == null || matchTeamB == null) { throw new RegistrationException( - ErrorCode.INVALID_MATCH_STATE, - "Match teams are not assigned"); + ErrorCode.INVALID_MATCH_STATE, + "Match teams are not assigned"); } boolean directMatch = providedTeamA.equals(matchTeamA.getId()) - && providedTeamB.equals(matchTeamB.getId()); + && providedTeamB.equals(matchTeamB.getId()); boolean reverseMatch = providedTeamA.equals(matchTeamB.getId()) - && providedTeamB.equals(matchTeamA.getId()); + && providedTeamB.equals(matchTeamA.getId()); if (!directMatch && !reverseMatch) { throw new RegistrationException( - ErrorCode.TEAM_MISMATCH, - "Provided team IDs do not match the teams assigned to the match"); + ErrorCode.TEAM_MISMATCH, + "Provided team IDs do not match the teams assigned to the match"); } } private MatchResult buildMatchResult(Match match, Team team, Integer score) { - MatchResult matchResult = new MatchResult(); - matchResult.setMatch(match); - matchResult.setTeam(team); - matchResult.setScore(score); - return matchResult; - } - - public static class RegistrationException extends RuntimeException { - private final ErrorCode errorCode; - - public RegistrationException(ErrorCode errorCode, String message) { - super(message); - this.errorCode = errorCode; - } - - public ErrorCode getErrorCode() { - return errorCode; - } - - public HttpStatus getStatus() { - return errorCode.getStatus(); - } + return MatchResult.create(score, match, team); } public enum ErrorCode { @@ -169,4 +150,21 @@ public HttpStatus getStatus() { return status; } } + + public static class RegistrationException extends RuntimeException { + private final ErrorCode errorCode; + + public RegistrationException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = errorCode; + } + + public ErrorCode getErrorCode() { + return errorCode; + } + + public HttpStatus getStatus() { + return errorCode.getStatus(); + } + } } diff --git a/src/test/java/cat/udl/eps/softarch/fll/TeamMemberTest.java b/src/test/java/cat/udl/eps/softarch/fll/TeamMemberTest.java index f1795bb2..6ed28628 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/TeamMemberTest.java +++ b/src/test/java/cat/udl/eps/softarch/fll/TeamMemberTest.java @@ -1,26 +1,21 @@ package cat.udl.eps.softarch.fll; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import java.time.LocalDate; +import cat.udl.eps.softarch.fll.domain.Team; +import cat.udl.eps.softarch.fll.domain.TeamMember; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import cat.udl.eps.softarch.fll.domain.Team; -import cat.udl.eps.softarch.fll.domain.TeamMember; +import java.time.LocalDate; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; class TeamMemberTest { - private Team team; private TeamMember member; @BeforeEach void setUp() { - team = new Team("UdL Eagles"); - member = new TeamMember(); - member.setName("Joan"); - member.setBirthDate(LocalDate.of(2005, 5, 20)); - member.setRole("Developer"); - member.setTeam(team); + Team team = Team.create("UdL Eagles", "Igualada", 2005, "Junior"); + member = TeamMember.create("Joan", "Developer", LocalDate.of(2005, 5, 20), team); } @Test @@ -41,10 +36,10 @@ void testMemberTeamRelation() { @Test @DisplayName("Compare equality by ID") void testEquals() { - TeamMember member1 = new TeamMember(); + TeamMember member1 = TeamMember.create("Joan", "Developer", LocalDate.of(2005, 5, 20), member.getTeam()); member1.setId(1L); - TeamMember member2 = new TeamMember(); + TeamMember member2 = TeamMember.create("Pep", "Developer", LocalDate.of(2005, 5, 20), member.getTeam()); member2.setId(1L); assertEquals(member1, member2, "Two members with the same ID should be equal"); diff --git a/src/test/java/cat/udl/eps/softarch/fll/TeamTest.java b/src/test/java/cat/udl/eps/softarch/fll/TeamTest.java index 42350731..2c439ebf 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/TeamTest.java +++ b/src/test/java/cat/udl/eps/softarch/fll/TeamTest.java @@ -1,34 +1,32 @@ package cat.udl.eps.softarch.fll; +import cat.udl.eps.softarch.fll.domain.Team; +import cat.udl.eps.softarch.fll.domain.TeamMember; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import java.time.LocalDate; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; -import java.time.LocalDate; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import cat.udl.eps.softarch.fll.domain.Team; -import cat.udl.eps.softarch.fll.domain.TeamMember; class TeamTest { private Team team; @BeforeEach void setUp() { - team = new Team("UdL Eagles"); - team.setCity("Igualada"); - team.setCategory("Senior"); + team = Team.create("UdL Eagles", "Igualada", 2000, "Senior"); } @Test @DisplayName("Validate max 10 team members") void testMemberLimit() { for (int i = 0; i < 10; i++) { - team.addMember(new TeamMember()); + TeamMember.create("Member " + i, "role" + i, LocalDate.of(2000, 1, 1), team); } - TeamMember extraMember = new TeamMember(); - assertThrows(IllegalStateException.class, () -> team.addMember(extraMember)); + LocalDate birthDate = LocalDate.of(2000, 1, 1); + assertThrows(IllegalStateException.class, () -> TeamMember.create("ExtraMember", "role" + 10, birthDate, team)); } @Test diff --git a/src/test/java/cat/udl/eps/softarch/fll/controller/MatchAssignmentControllerTest.java b/src/test/java/cat/udl/eps/softarch/fll/controller/MatchAssignmentControllerTest.java index d9228725..af929cbb 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/controller/MatchAssignmentControllerTest.java +++ b/src/test/java/cat/udl/eps/softarch/fll/controller/MatchAssignmentControllerTest.java @@ -35,16 +35,16 @@ void setUp() { validator.afterPropertiesSet(); mockMvc = MockMvcBuilders.standaloneSetup(controller) - .setControllerAdvice(new MatchAssignmentExceptionHandler()) - .setValidator(validator) - .build(); + .setControllerAdvice(new MatchAssignmentExceptionHandler()) + .setValidator(validator) + .build(); } @Test void assignRefereeReturnsAssignedResponse() throws Exception { Match match = new Match(); match.setId(1L); - Referee referee = new Referee(); + Referee referee = Referee.create("name", "email@email.com", "123456789"); referee.setId(2L); match.setReferee(referee); @@ -62,9 +62,9 @@ void assignRefereeReturnsAssignedResponse() throws Exception { @Test void assignRefereeReturnsErrorResponse() throws Exception { when(matchAssignmentService.assignReferee("1", "2")).thenThrow( - new MatchAssignmentException( - MatchAssignmentErrorCode.AVAILABILITY_CONFLICT, - "Referee is already assigned to another overlapping match")); + new MatchAssignmentException( + MatchAssignmentErrorCode.AVAILABILITY_CONFLICT, + "Referee is already assigned to another overlapping match")); mockMvc.perform(post("/matchAssignments/assign") .contentType(MediaType.APPLICATION_JSON) @@ -80,51 +80,51 @@ void assignRefereeReturnsErrorResponse() throws Exception { @Test void assignBatchReturnsAssignedResponse() throws Exception { BatchMatchAssignmentResponse response = new BatchMatchAssignmentResponse( - "3", - "ASSIGNED", - 2, - List.of( - new BatchMatchAssignmentItemResponse("10", "20", "ASSIGNED"), - new BatchMatchAssignmentItemResponse("11", "21", "ASSIGNED"))); + "3", + "ASSIGNED", + 2, + List.of( + new BatchMatchAssignmentItemResponse("10", "20", "ASSIGNED"), + new BatchMatchAssignmentItemResponse("11", "21", "ASSIGNED"))); when(matchAssignmentService.assignBatch( - "3", - List.of( - new BatchMatchAssignmentItemRequest("10", "20"), - new BatchMatchAssignmentItemRequest("11", "21")))).thenReturn(response); + "3", + List.of( + new BatchMatchAssignmentItemRequest("10", "20"), + new BatchMatchAssignmentItemRequest("11", "21")))).thenReturn(response); mockMvc.perform(post("/matchAssignments/batch") .contentType(MediaType.APPLICATION_JSON) .content(""" - { - "roundId": "3", - "assignments": [ - {"matchId":"10","refereeId":"20"}, - {"matchId":"11","refereeId":"21"} - ] - } - """)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.roundId").value("3")) - .andExpect(jsonPath("$.status").value("ASSIGNED")) - .andExpect(jsonPath("$.processed").value(2)) - .andExpect(jsonPath("$.assignments[0].matchId").value("10")) - .andExpect(jsonPath("$.assignments[1].refereeId").value("21")); + { + "roundId": "3", + "assignments": [ + {"matchId":"10","refereeId":"20"}, + {"matchId":"11","refereeId":"21"} + ] + } + """)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.roundId").value("3")) + .andExpect(jsonPath("$.status").value("ASSIGNED")) + .andExpect(jsonPath("$.processed").value(2)) + .andExpect(jsonPath("$.assignments[0].matchId").value("10")) + .andExpect(jsonPath("$.assignments[1].refereeId").value("21")); } @Test void assignBatchReturnsDetailedErrorResponse() throws Exception { when(matchAssignmentService.assignBatch( - "3", - List.of( - new BatchMatchAssignmentItemRequest("10", "20"), - new BatchMatchAssignmentItemRequest("11", "20")))).thenThrow( - new MatchAssignmentException( - MatchAssignmentErrorCode.AVAILABILITY_CONFLICT, - "Referee is assigned to overlapping matches in the same batch", - 1, - "11", - "20")); + "3", + List.of( + new BatchMatchAssignmentItemRequest("10", "20"), + new BatchMatchAssignmentItemRequest("11", "20")))).thenThrow( + new MatchAssignmentException( + MatchAssignmentErrorCode.AVAILABILITY_CONFLICT, + "Referee is assigned to overlapping matches in the same batch", + 1, + "11", + "20")); mockMvc.perform(post("/matchAssignments/batch") .contentType(MediaType.APPLICATION_JSON) diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/AwardValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/AwardValidationTest.java new file mode 100644 index 00000000..cb6b54cd --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/AwardValidationTest.java @@ -0,0 +1,50 @@ +package cat.udl.eps.softarch.fll.domain; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class AwardValidationTest { + + private final Edition validEdition = Edition.create(2024, "Lleida Arena", "FLL Season"); + private final Team validTeam = Team.create("Winners", "Barcelona", 2000, "category"); + + @Test + void validConstruction() { + assertDoesNotThrow(() -> Award.create("Best Robot", validEdition, validTeam)); + } + + @Nested + class EmptyName { + + @Test + void nullNameThrows() { + assertThrows(DomainValidationException.class, + () -> Award.create(null, validEdition, validTeam)); + } + + @Test + void blankNameThrows() { + assertThrows(DomainValidationException.class, + () -> Award.create(" ", validEdition, validTeam)); + } + } + + @Nested + class NullRequiredReference { + + @Test + void nullEditionThrows() { + assertThrows(DomainValidationException.class, + () -> Award.create("Best Robot", null, validTeam)); + } + + @Test + void nullWinnerThrows() { + assertThrows(DomainValidationException.class, + () -> Award.create("Best Robot", validEdition, null)); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/CoachValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/CoachValidationTest.java new file mode 100644 index 00000000..8fd1e03d --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/CoachValidationTest.java @@ -0,0 +1,58 @@ +package cat.udl.eps.softarch.fll.domain; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class CoachValidationTest { + + @Test + void validConstruction() { + assertDoesNotThrow(() -> Coach.create("John Doe", "john@example.com")); + } + + @Nested + class EmptyName { + + @Test + void nullNameThrows() { + assertThrows(DomainValidationException.class, + () -> Coach.create(null, "john@example.com")); + } + + @Test + void blankNameThrows() { + assertThrows(DomainValidationException.class, + () -> Coach.create(" ", "john@example.com")); + } + } + + @Nested + class InvalidEmail { + + @Test + void nullEmailThrows() { + assertThrows(DomainValidationException.class, + () -> Coach.create("John Doe", null)); + } + + @Test + void blankEmailThrows() { + assertThrows(DomainValidationException.class, + () -> Coach.create("John Doe", "")); + } + + @Test + void invalidEmailFormatThrows() { + assertThrows(DomainValidationException.class, + () -> Coach.create("John Doe", "not-an-email")); + } + + @Test + void emailWithoutDomainThrows() { + assertThrows(DomainValidationException.class, + () -> Coach.create("John Doe", "john@")); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/CompetitionTableValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/CompetitionTableValidationTest.java new file mode 100644 index 00000000..c6326798 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/CompetitionTableValidationTest.java @@ -0,0 +1,37 @@ +package cat.udl.eps.softarch.fll.domain; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class CompetitionTableValidationTest { + + @Test + void validConstruction() { + assertDoesNotThrow(() -> CompetitionTable.create("TABLE-1")); + } + + @Nested + class NullId { + + @Test + void nullIdThrows() { + assertThrows(DomainValidationException.class, + () -> CompetitionTable.create(null)); + } + + @Test + void blankIdThrows() { + assertThrows(DomainValidationException.class, + () -> CompetitionTable.create(" ")); + } + + @Test + void emptyIdThrows() { + assertThrows(DomainValidationException.class, + () -> CompetitionTable.create("")); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/DomainValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/DomainValidationTest.java new file mode 100644 index 00000000..48836906 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/DomainValidationTest.java @@ -0,0 +1,251 @@ +package cat.udl.eps.softarch.fll.domain; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import java.time.LocalDate; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class DomainValidationTest { + + @Nested + class RequireNonBlank { + + @Test + void acceptsNonBlank() { + assertDoesNotThrow(() -> DomainValidation.requireNonBlank("hello", "field")); + } + + @Test + void rejectsNull() { + DomainValidationException ex = assertThrows(DomainValidationException.class, + () -> DomainValidation.requireNonBlank(null, "field")); + assertEquals("field must not be null", ex.getMessage()); + } + + @Test + void rejectsBlank() { + DomainValidationException ex = assertThrows(DomainValidationException.class, + () -> DomainValidation.requireNonBlank(" ", "field")); + assertEquals("field must not be blank", ex.getMessage()); + } + + @Test + void rejectsEmpty() { + DomainValidationException ex = assertThrows(DomainValidationException.class, + () -> DomainValidation.requireNonBlank("", "field")); + assertEquals("field must not be blank", ex.getMessage()); + } + } + + @Nested + class RequireValidEmail { + + @Test + void acceptsValidEmail() { + assertDoesNotThrow(() -> DomainValidation.requireValidEmail("user@example.com", "email")); + } + + @Test + void rejectsNull() { + assertThrows(DomainValidationException.class, + () -> DomainValidation.requireValidEmail(null, "email")); + } + + @Test + void rejectsInvalidFormat() { + assertThrows(DomainValidationException.class, + () -> DomainValidation.requireValidEmail("not-an-email", "email")); + } + + @Test + void rejectsMissingDomain() { + assertThrows(DomainValidationException.class, + () -> DomainValidation.requireValidEmail("user@", "email")); + } + + @Test + void rejectsMissingAt() { + assertThrows(DomainValidationException.class, + () -> DomainValidation.requireValidEmail("userexample.com", "email")); + } + + @Test + void acceptsLocalPartWithSingleDot() { + assertDoesNotThrow(() -> DomainValidation.requireValidEmail("first.last@example.com", "email")); + } + } + + @Nested + class RequireNonNegative { + + @Test + void acceptsZero() { + assertDoesNotThrow(() -> DomainValidation.requireNonNegative(0, "score")); + } + + @Test + void acceptsPositive() { + assertDoesNotThrow(() -> DomainValidation.requireNonNegative(100, "score")); + } + + @Test + void rejectsNull() { + assertThrows(DomainValidationException.class, + () -> DomainValidation.requireNonNegative(null, "score")); + } + + @Test + void rejectsNegative() { + DomainValidationException ex = assertThrows(DomainValidationException.class, + () -> DomainValidation.requireNonNegative(-1, "score")); + assertEquals("score must not be negative", ex.getMessage()); + } + } + + @Nested + class RequireNonNull { + + @Test + void acceptsNonNull() { + assertDoesNotThrow(() -> DomainValidation.requireNonNull("abc", "id")); + } + + @Test + void rejectsNull() { + DomainValidationException ex = assertThrows(DomainValidationException.class, + () -> DomainValidation.requireNonNull(null, "id")); + assertEquals("id must not be null", ex.getMessage()); + } + } + + @Nested + class RequireMin { + + @Test + void acceptsValueAtMinimum() { + assertDoesNotThrow(() -> DomainValidation.requireMin(5, 5, "age")); + } + + @Test + void acceptsValueAboveMinimum() { + assertDoesNotThrow(() -> DomainValidation.requireMin(10, 5, "age")); + } + + @Test + void rejectsNull() { + assertThrows(DomainValidationException.class, + () -> DomainValidation.requireMin(null, 5, "age")); + } + + @Test + void rejectsBelowMinimum() { + DomainValidationException ex = assertThrows(DomainValidationException.class, + () -> DomainValidation.requireMin(4, 5, "age")); + assertEquals("age must not be less than 5", ex.getMessage()); + } + } + + @Nested + class RequirePast { + + @Test + void acceptsDateInThePast() { + LocalDate yesterday = LocalDate.now().minusDays(1); + assertDoesNotThrow(() -> DomainValidation.requirePast(yesterday, "birthDate")); + } + + @Test + void rejectsNull() { + assertThrows(DomainValidationException.class, + () -> DomainValidation.requirePast(null, "birthDate")); + } + + @Test + void rejectsToday() { + LocalDate today = LocalDate.now(); + DomainValidationException ex = assertThrows(DomainValidationException.class, + () -> DomainValidation.requirePast(today, "birthDate")); + assertEquals("birthDate must be in the past", ex.getMessage()); + } + + @Test + void rejectsFutureDate() { + LocalDate tomorrow = LocalDate.now().plusDays(1); + assertThrows(DomainValidationException.class, + () -> DomainValidation.requirePast(tomorrow, "birthDate")); + } + } + + @Nested + class RequireLengthBetween { + + @Test + void acceptsLengthAtMinimum() { + assertDoesNotThrow(() -> DomainValidation.requireLengthBetween("ab", 2, 5, "code")); + } + + @Test + void acceptsLengthAtMaximum() { + assertDoesNotThrow(() -> DomainValidation.requireLengthBetween("abcde", 2, 5, "code")); + } + + @Test + void acceptsLengthWithinBounds() { + assertDoesNotThrow(() -> DomainValidation.requireLengthBetween("abc", 2, 5, "code")); + } + + @Test + void rejectsNull() { + assertThrows(DomainValidationException.class, + () -> DomainValidation.requireLengthBetween(null, 2, 5, "code")); + } + + @Test + void rejectsBelowMinimum() { + DomainValidationException ex = assertThrows(DomainValidationException.class, + () -> DomainValidation.requireLengthBetween("a", 2, 5, "code")); + assertEquals("code length must not be less than 2", ex.getMessage()); + } + + @Test + void rejectsAboveMaximum() { + DomainValidationException ex = assertThrows(DomainValidationException.class, + () -> DomainValidation.requireLengthBetween("abcdef", 2, 5, "code")); + assertEquals("code length must not be more than 5", ex.getMessage()); + } + } + + @Nested + class RequireMaxLength { + + @Test + void acceptsLengthAtMaximum() { + assertDoesNotThrow(() -> DomainValidation.requireMaxLength("abcde", 5, "name")); + } + + @Test + void acceptsLengthBelowMaximum() { + assertDoesNotThrow(() -> DomainValidation.requireMaxLength("abc", 5, "name")); + } + + @Test + void acceptsEmptyString() { + assertDoesNotThrow(() -> DomainValidation.requireMaxLength("", 5, "name")); + } + + @Test + void rejectsNull() { + assertThrows(DomainValidationException.class, + () -> DomainValidation.requireMaxLength(null, 5, "name")); + } + + @Test + void rejectsAboveMaximum() { + DomainValidationException ex = assertThrows(DomainValidationException.class, + () -> DomainValidation.requireMaxLength("abcdef", 5, "name")); + assertEquals("name length must not be more than 5", ex.getMessage()); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/EditionValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/EditionValidationTest.java new file mode 100644 index 00000000..c316d84c --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/EditionValidationTest.java @@ -0,0 +1,46 @@ +package cat.udl.eps.softarch.fll.domain; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class EditionValidationTest { + + @Test + void validConstruction() { + assertDoesNotThrow(() -> Edition.create(2024, "Lleida Arena", "FLL Season")); + } + + @Nested + class NullRequiredField { + + @Test + void nullYearThrows() { + assertThrows(DomainValidationException.class, + () -> Edition.create(null, "Lleida Arena", "FLL Season")); + } + } + + @Nested + class EmptyName { + + @Test + void blankVenueNameThrows() { + assertThrows(DomainValidationException.class, + () -> Edition.create(2024, " ", "FLL Season")); + } + + @Test + void nullVenueNameThrows() { + assertThrows(DomainValidationException.class, + () -> Edition.create(2024, null, "FLL Season")); + } + + @Test + void blankDescriptionThrows() { + assertThrows(DomainValidationException.class, + () -> Edition.create(2024, "Lleida Arena", "")); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/FloaterValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/FloaterValidationTest.java new file mode 100644 index 00000000..e32d2044 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/FloaterValidationTest.java @@ -0,0 +1,57 @@ +package cat.udl.eps.softarch.fll.domain; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class FloaterValidationTest { + + @Test + void validConstruction() { + assertDoesNotThrow( + () -> Floater.create("Alice", "alice@example.com", "123456789", "STU001")); + } + + @Nested + class EmptyName { + + @Test + void nullNameThrows() { + assertThrows(DomainValidationException.class, + () -> Floater.create(null, "alice@example.com", "123456789", "STU001")); + } + + @Test + void blankNameThrows() { + assertThrows(DomainValidationException.class, + () -> Floater.create("", "alice@example.com", "123456789", "STU001")); + } + } + + @Nested + class InvalidEmail { + + @Test + void invalidEmailThrows() { + assertThrows(DomainValidationException.class, + () -> Floater.create("Alice", "not-valid", "123456789", "STU001")); + } + } + + @Nested + class NullRequiredField { + + @Test + void nullStudentCodeThrows() { + assertThrows(DomainValidationException.class, + () -> Floater.create("Alice", "alice@example.com", "123456789", null)); + } + + @Test + void blankStudentCodeThrows() { + assertThrows(DomainValidationException.class, + () -> Floater.create("Alice", "alice@example.com", "123456789", " ")); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/MatchResultValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/MatchResultValidationTest.java new file mode 100644 index 00000000..cf44487e --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/MatchResultValidationTest.java @@ -0,0 +1,55 @@ +package cat.udl.eps.softarch.fll.domain; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class MatchResultValidationTest { + + private final Match validMatch = new Match(); + private final Team validTeam = Team.create("ValidTeam", "Barcelona", 2000, "category"); + + @Test + void validConstruction() { + assertDoesNotThrow(() -> MatchResult.create(100, validMatch, validTeam)); + } + + @Test + void zeroScoreIsValid() { + assertDoesNotThrow(() -> MatchResult.create(0, validMatch, validTeam)); + } + + @Nested + class NegativeScore { + + @Test + void negativeScoreThrows() { + assertThrows(DomainValidationException.class, + () -> MatchResult.create(-1, validMatch, validTeam)); + } + + @Test + void nullScoreThrows() { + assertThrows(DomainValidationException.class, + () -> MatchResult.create(null, validMatch, validTeam)); + } + } + + @Nested + class NullRequiredReference { + + @Test + void nullMatchThrows() { + assertThrows(DomainValidationException.class, + () -> MatchResult.create(50, null, validTeam)); + } + + @Test + void nullTeamThrows() { + assertThrows(DomainValidationException.class, + () -> MatchResult.create(50, validMatch, null)); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/MediaContentValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/MediaContentValidationTest.java new file mode 100644 index 00000000..5f13a8a5 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/MediaContentValidationTest.java @@ -0,0 +1,47 @@ +package cat.udl.eps.softarch.fll.domain; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class MediaContentValidationTest { + + @Test + void validConstruction() { + assertDoesNotThrow(() -> MediaContent.create("https://example.com/video.mp4", "video")); + } + + @Nested + class InvalidUrl { + + @Test + void nullUrlThrows() { + assertThrows(DomainValidationException.class, + () -> MediaContent.create(null, "video")); + } + + @Test + void blankUrlThrows() { + assertThrows(DomainValidationException.class, + () -> MediaContent.create("", "video")); + } + } + + @Nested + class InvalidType { + + @Test + void nullTypeThrows() { + assertThrows(DomainValidationException.class, + () -> MediaContent.create("https://example.com/video.mp4", null)); + } + + @Test + void blankTypeThrows() { + assertThrows(DomainValidationException.class, + () -> MediaContent.create("https://example.com/video.mp4", "")); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/RecordValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/RecordValidationTest.java new file mode 100644 index 00000000..772cb4de --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/RecordValidationTest.java @@ -0,0 +1,34 @@ +package cat.udl.eps.softarch.fll.domain; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class RecordValidationTest { + + @Test + void validConstruction() { + assertDoesNotThrow(() -> Record.create("My Record")); + } + + @Nested + class EmptyName { + + @Test + void nullNameThrows() { + assertThrows(DomainValidationException.class, () -> Record.create(null)); + } + + @Test + void blankNameThrows() { + assertThrows(DomainValidationException.class, () -> Record.create(" ")); + } + + @Test + void emptyNameThrows() { + assertThrows(DomainValidationException.class, () -> Record.create("")); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/RefereeValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/RefereeValidationTest.java new file mode 100644 index 00000000..d107ba5c --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/RefereeValidationTest.java @@ -0,0 +1,56 @@ +package cat.udl.eps.softarch.fll.domain; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class RefereeValidationTest { + + @Test + void validConstruction() { + assertDoesNotThrow(() -> Referee.create("Jane Doe", "jane@example.com", "123456789")); + } + + @Nested + class EmptyName { + + @Test + void nullNameThrows() { + assertThrows(DomainValidationException.class, + () -> Referee.create(null, "jane@example.com", "123456789")); + } + + @Test + void blankNameThrows() { + assertThrows(DomainValidationException.class, + () -> Referee.create(" ", "jane@example.com", "123456789")); + } + } + + @Nested + class InvalidEmail { + + @Test + void invalidEmailThrows() { + assertThrows(DomainValidationException.class, + () -> Referee.create("Jane Doe", "bad-email", "123456789")); + } + + @Test + void nullEmailThrows() { + assertThrows(DomainValidationException.class, + () -> Referee.create("Jane Doe", null, "123456789")); + } + } + + @Nested + class NullRequiredField { + + @Test + void nullPhoneThrows() { + assertThrows(DomainValidationException.class, + () -> Referee.create("Jane Doe", "jane@example.com", null)); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/ScientificProjectValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/ScientificProjectValidationTest.java new file mode 100644 index 00000000..d978a804 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/ScientificProjectValidationTest.java @@ -0,0 +1,41 @@ +package cat.udl.eps.softarch.fll.domain; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class ScientificProjectValidationTest { + + @Test + void validConstructionWithScore() { + assertDoesNotThrow(() -> ScientificProject.create(85)); + } + + @Test + void validConstructionWithZeroScore() { + assertDoesNotThrow(() -> ScientificProject.create(0)); + } + + @Test + void invalidConstructionWithNullScore() { + assertThrows(DomainValidationException.class, () -> ScientificProject.create(null)); + } + + @Nested + class NegativeScore { + + @Test + void negativeScoreThrows() { + assertThrows(DomainValidationException.class, + () -> ScientificProject.create(-1)); + } + + @Test + void largeNegativeScoreThrows() { + assertThrows(DomainValidationException.class, + () -> ScientificProject.create(-100)); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/TeamMemberValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/TeamMemberValidationTest.java new file mode 100644 index 00000000..917b25c9 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/TeamMemberValidationTest.java @@ -0,0 +1,61 @@ +package cat.udl.eps.softarch.fll.domain; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import java.time.LocalDate; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class TeamMemberValidationTest { + + private final Team validTeam = Team.create("TestTeam", "Barcelona", 2000, "category"); + + @Test + void validConstruction() { + LocalDate birthDate = LocalDate.ofYearDay(0, 1); + assertDoesNotThrow(() -> TeamMember.create("Alice", "Player", birthDate, validTeam)); + } + + @Test + void futureDateThrows() { + LocalDate tomorrow = LocalDate.now().plusDays(1); + assertThrows(DomainValidationException.class, + () -> TeamMember.create("Alice", "Player", tomorrow, validTeam)); + } + + @Nested + class EmptyName { + + @Test + void nullNameThrows() { + LocalDate birthDate = LocalDate.ofYearDay(0, 1); + assertThrows(DomainValidationException.class, + () -> TeamMember.create(null, "Player", birthDate, validTeam)); + } + + @Test + void blankNameThrows() { + LocalDate birthDate = LocalDate.ofYearDay(0, 1); + assertThrows(DomainValidationException.class, + () -> TeamMember.create(" ", "Player", birthDate, validTeam)); + } + + @Test + void blankRoleThrows() { + LocalDate birthDate = LocalDate.ofYearDay(1, 1); + assertThrows(DomainValidationException.class, + () -> TeamMember.create("Alice", "", birthDate, validTeam)); + } + } + + @Nested + class NullRequiredReference { + + @Test + void nullTeamThrows() { + LocalDate birthDate = LocalDate.ofYearDay(0, 1); + assertThrows(DomainValidationException.class, + () -> TeamMember.create("Alice", "Player", birthDate, null)); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/TeamValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/TeamValidationTest.java new file mode 100644 index 00000000..de622e59 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/TeamValidationTest.java @@ -0,0 +1,72 @@ +package cat.udl.eps.softarch.fll.domain; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class TeamValidationTest { + + @Test + void validConstruction() { + assertDoesNotThrow(() -> Team.create("Robotics", "Lleida", 2020, "Challenge")); + } + + @Test + void invalidMinFoundationYearConstruction() { + assertThrows(DomainValidationException.class, () -> Team.create("Robotics", "Barcelona", 0, "category")); + } + + @Test + void nullNameThrows() { + DomainValidationException ex = assertThrows(DomainValidationException.class, + () -> Team.create(null, "Lleida", 2020, "Challenge")); + assertEquals("name must not be null", ex.getMessage()); + } + + @Test + void nullCityThrows() { + DomainValidationException ex = assertThrows(DomainValidationException.class, + () -> Team.create("Robotics", null, 2000, "category")); + assertEquals("city must not be null", ex.getMessage()); + } + + @Nested + class EmptyName { + + @Test + void blankNameThrows() { + assertThrows(DomainValidationException.class, + () -> Team.create(" ", "Lleida", 2020, "Challenge")); + } + + @Test + void emptyNameThrows() { + assertThrows(DomainValidationException.class, + () -> Team.create("", "Lleida", 2020, "Challenge")); + } + + @Test + void blankCityThrows() { + assertThrows(DomainValidationException.class, + () -> Team.create("Robotics", " ", 2020, "Challenge")); + } + + @Test + void blankCategoryThrows() { + assertThrows(DomainValidationException.class, + () -> Team.create("Robotics", "Lleida", 2020, "")); + } + } + + @Nested + class NullRequiredField { + + @Test + void nullFoundationYearThrows() { + assertThrows(DomainValidationException.class, + () -> Team.create("Robotics", "Lleida", null, "Challenge")); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/UserValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/UserValidationTest.java new file mode 100644 index 00000000..53eba35b --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/UserValidationTest.java @@ -0,0 +1,68 @@ +package cat.udl.eps.softarch.fll.domain; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class UserValidationTest { + + @Test + void validConstruction() { + assertDoesNotThrow(() -> User.create("admin", "admin@example.com", "securepass")); + } + + @Nested + class NullId { + + @Test + void nullIdThrows() { + assertThrows(DomainValidationException.class, + () -> User.create(null, "admin@example.com", "securepass")); + } + + @Test + void blankIdThrows() { + assertThrows(DomainValidationException.class, + () -> User.create(" ", "admin@example.com", "securepass")); + } + } + + @Nested + class InvalidEmail { + + @Test + void nullEmailThrows() { + assertThrows(DomainValidationException.class, + () -> User.create("admin", null, "securepass")); + } + + @Test + void invalidEmailFormatThrows() { + assertThrows(DomainValidationException.class, + () -> User.create("admin", "not-an-email", "securepass")); + } + + @Test + void blankEmailThrows() { + assertThrows(DomainValidationException.class, + () -> User.create("admin", "", "securepass")); + } + } + + @Nested + class EmptyPassword { + + @Test + void nullPasswordThrows() { + assertThrows(DomainValidationException.class, + () -> User.create("admin", "admin@example.com", null)); + } + + @Test + void blankPasswordThrows() { + assertThrows(DomainValidationException.class, + () -> User.create("admin", "admin@example.com", " ")); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/domain/VenueValidationTest.java b/src/test/java/cat/udl/eps/softarch/fll/domain/VenueValidationTest.java new file mode 100644 index 00000000..7a1c0e7a --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/fll/domain/VenueValidationTest.java @@ -0,0 +1,46 @@ +package cat.udl.eps.softarch.fll.domain; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class VenueValidationTest { + + @Test + void validConstruction() { + assertDoesNotThrow(() -> Venue.create("Lleida Arena", "Lleida")); + } + + @Nested + class EmptyName { + + @Test + void nullNameThrows() { + assertThrows(DomainValidationException.class, + () -> Venue.create(null, "Lleida")); + } + + @Test + void blankNameThrows() { + assertThrows(DomainValidationException.class, + () -> Venue.create(" ", "Lleida")); + } + } + + @Nested + class EmptyCity { + @Test + void nullCityThrows() { + assertThrows(DomainValidationException.class, + () -> Venue.create("Lleida Arena", null)); + } + + @Test + void blankCityThrows() { + assertThrows(DomainValidationException.class, + () -> Venue.create("Lleida Arena", "")); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/fll/service/EditionLifecycleServiceTest.java b/src/test/java/cat/udl/eps/softarch/fll/service/EditionLifecycleServiceTest.java index 0a7f7f7a..0bf5e28b 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/service/EditionLifecycleServiceTest.java +++ b/src/test/java/cat/udl/eps/softarch/fll/service/EditionLifecycleServiceTest.java @@ -1,22 +1,22 @@ package cat.udl.eps.softarch.fll.service; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import java.util.Optional; +import cat.udl.eps.softarch.fll.domain.Edition; +import cat.udl.eps.softarch.fll.domain.EditionOperation; +import cat.udl.eps.softarch.fll.domain.EditionState; +import cat.udl.eps.softarch.fll.exception.EditionLifecycleException; +import cat.udl.eps.softarch.fll.repository.EditionRepository; 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 cat.udl.eps.softarch.fll.domain.Edition; -import cat.udl.eps.softarch.fll.domain.EditionOperation; -import cat.udl.eps.softarch.fll.domain.EditionState; -import cat.udl.eps.softarch.fll.exception.EditionLifecycleException; -import cat.udl.eps.softarch.fll.repository.EditionRepository; +import java.util.Optional; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class EditionLifecycleServiceTest { @@ -31,7 +31,7 @@ class EditionLifecycleServiceTest { @BeforeEach void setUp() { - edition = new Edition(); + edition = Edition.create(2026, "Test Edition", "description"); edition.setId(1L); edition.setState(EditionState.DRAFT); } @@ -67,8 +67,8 @@ void changeStateShouldRejectOpenToDraft() { when(editionRepository.findByIdForUpdate(1L)).thenReturn(Optional.of(edition)); EditionLifecycleException ex = assertThrows( - EditionLifecycleException.class, - () -> editionLifecycleService.changeState(1L, EditionState.DRAFT)); + EditionLifecycleException.class, + () -> editionLifecycleService.changeState(1L, EditionState.DRAFT)); assertEquals("INVALID_EDITION_STATE_TRANSITION", ex.getError()); } @@ -79,8 +79,8 @@ void changeStateShouldRejectTransitionsFromClosed() { when(editionRepository.findByIdForUpdate(1L)).thenReturn(Optional.of(edition)); EditionLifecycleException ex = assertThrows( - EditionLifecycleException.class, - () -> editionLifecycleService.changeState(1L, EditionState.OPEN)); + EditionLifecycleException.class, + () -> editionLifecycleService.changeState(1L, EditionState.OPEN)); assertEquals("INVALID_EDITION_STATE_TRANSITION", ex.getError()); } @@ -91,8 +91,8 @@ void changeStateShouldRejectClosedToDraft() { when(editionRepository.findByIdForUpdate(1L)).thenReturn(Optional.of(edition)); EditionLifecycleException ex = assertThrows( - EditionLifecycleException.class, - () -> editionLifecycleService.changeState(1L, EditionState.DRAFT)); + EditionLifecycleException.class, + () -> editionLifecycleService.changeState(1L, EditionState.DRAFT)); assertEquals("INVALID_EDITION_STATE_TRANSITION", ex.getError()); } @@ -102,8 +102,8 @@ void changeStateShouldRejectSameStateTransition() { when(editionRepository.findByIdForUpdate(1L)).thenReturn(Optional.of(edition)); EditionLifecycleException ex = assertThrows( - EditionLifecycleException.class, - () -> editionLifecycleService.changeState(1L, EditionState.DRAFT)); + EditionLifecycleException.class, + () -> editionLifecycleService.changeState(1L, EditionState.DRAFT)); assertEquals("INVALID_EDITION_STATE_TRANSITION", ex.getError()); } @@ -113,8 +113,8 @@ void changeStateShouldThrowNotFoundWhenEditionMissing() { when(editionRepository.findByIdForUpdate(1L)).thenReturn(Optional.empty()); EditionLifecycleException ex = assertThrows( - EditionLifecycleException.class, - () -> editionLifecycleService.changeState(1L, EditionState.OPEN)); + EditionLifecycleException.class, + () -> editionLifecycleService.changeState(1L, EditionState.OPEN)); assertEquals("EDITION_NOT_FOUND", ex.getError()); } @@ -142,8 +142,8 @@ void assertOperationAllowedShouldAllowTeamRegistrationWhenOpen() { @Test void assertOperationAllowedShouldRejectTeamRegistrationWhenDraft() { EditionLifecycleException ex = assertThrows( - EditionLifecycleException.class, - () -> editionLifecycleService.assertOperationAllowed(edition, EditionOperation.TEAM_REGISTRATION)); + EditionLifecycleException.class, + () -> editionLifecycleService.assertOperationAllowed(edition, EditionOperation.TEAM_REGISTRATION)); assertEquals("EDITION_OPERATION_NOT_ALLOWED", ex.getError()); } @@ -153,8 +153,8 @@ void assertOperationAllowedShouldRejectTeamRegistrationWhenClosed() { edition.setState(EditionState.CLOSED); EditionLifecycleException ex = assertThrows( - EditionLifecycleException.class, - () -> editionLifecycleService.assertOperationAllowed(edition, EditionOperation.TEAM_REGISTRATION)); + EditionLifecycleException.class, + () -> editionLifecycleService.assertOperationAllowed(edition, EditionOperation.TEAM_REGISTRATION)); assertEquals("EDITION_OPERATION_NOT_ALLOWED", ex.getError()); } @@ -164,8 +164,8 @@ void assertOperationAllowedShouldTreatNullStateAsDraft() { edition.setState(null); EditionLifecycleException ex = assertThrows( - EditionLifecycleException.class, - () -> editionLifecycleService.assertOperationAllowed(edition, EditionOperation.TEAM_REGISTRATION)); + EditionLifecycleException.class, + () -> editionLifecycleService.assertOperationAllowed(edition, EditionOperation.TEAM_REGISTRATION)); assertEquals("EDITION_OPERATION_NOT_ALLOWED", ex.getError()); assertEquals("Operation TEAM_REGISTRATION is not allowed when edition is in state DRAFT", ex.getMessage()); diff --git a/src/test/java/cat/udl/eps/softarch/fll/service/EditionVolunteerServiceTest.java b/src/test/java/cat/udl/eps/softarch/fll/service/EditionVolunteerServiceTest.java index 81f7f9fe..53a868c1 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/service/EditionVolunteerServiceTest.java +++ b/src/test/java/cat/udl/eps/softarch/fll/service/EditionVolunteerServiceTest.java @@ -1,16 +1,5 @@ package cat.udl.eps.softarch.fll.service; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; -import java.util.List; -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 cat.udl.eps.softarch.fll.controller.dto.EditionVolunteersResponse; import cat.udl.eps.softarch.fll.domain.Floater; import cat.udl.eps.softarch.fll.domain.Judge; @@ -20,6 +9,18 @@ import cat.udl.eps.softarch.fll.repository.FloaterRepository; import cat.udl.eps.softarch.fll.repository.JudgeRepository; import cat.udl.eps.softarch.fll.repository.RefereeRepository; +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 java.util.List; +import java.util.NoSuchElementException; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class EditionVolunteerServiceTest { @@ -41,24 +42,14 @@ class EditionVolunteerServiceTest { @Test void getVolunteersGroupedByTypeReturnsGroupedAndMappedResponse() { - Referee referee = new Referee(); + Referee referee = Referee.create("Ref One", "ref1@example.com", "111111111"); referee.setId(1L); - referee.setName("Ref One"); - referee.setEmailAddress("ref1@example.com"); - referee.setPhoneNumber("111111111"); - Judge judge = new Judge(); + Judge judge = Judge.create("Judge One", "judge1@example.com", "222222222"); judge.setId(2L); - judge.setName("Judge One"); - judge.setEmailAddress("judge1@example.com"); - judge.setPhoneNumber("222222222"); - Floater floater = new Floater(); + Floater floater = Floater.create("Floater One", "floater1@example.com", "333333333", "STU-1"); floater.setId(3L); - floater.setName("Floater One"); - floater.setEmailAddress("floater1@example.com"); - floater.setPhoneNumber("333333333"); - floater.setStudentCode("STU-1"); when(editionRepository.existsById(10L)).thenReturn(true); when(refereeRepository.findByEditionId(10L)).thenReturn(List.of(referee)); @@ -108,8 +99,8 @@ void getVolunteersGroupedByTypeThrowsWhenEditionDoesNotExist() { when(editionRepository.existsById(99L)).thenReturn(false); EditionVolunteerException exception = assertThrows( - EditionVolunteerException.class, - () -> editionVolunteerService.getVolunteersGroupedByType(99L)); + EditionVolunteerException.class, + () -> editionVolunteerService.getVolunteersGroupedByType(99L)); assertEquals("EDITION_NOT_FOUND", exception.getErrorCode()); assertEquals("Edition with id 99 not found", exception.getMessage()); diff --git a/src/test/java/cat/udl/eps/softarch/fll/service/MatchAssignmentServiceTest.java b/src/test/java/cat/udl/eps/softarch/fll/service/MatchAssignmentServiceTest.java index 7ecbcab1..75ada420 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/service/MatchAssignmentServiceTest.java +++ b/src/test/java/cat/udl/eps/softarch/fll/service/MatchAssignmentServiceTest.java @@ -1,20 +1,5 @@ package cat.udl.eps.softarch.fll.service; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import java.time.LocalTime; -import java.util.List; -import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; import cat.udl.eps.softarch.fll.controller.dto.BatchMatchAssignmentItemRequest; import cat.udl.eps.softarch.fll.controller.dto.BatchMatchAssignmentResponse; import cat.udl.eps.softarch.fll.domain.Floater; @@ -27,6 +12,21 @@ import cat.udl.eps.softarch.fll.repository.MatchRepository; import cat.udl.eps.softarch.fll.repository.RoundRepository; import cat.udl.eps.softarch.fll.repository.VolunteerRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import java.time.LocalTime; +import java.util.List; +import java.util.Optional; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class MatchAssignmentServiceTest { @@ -53,7 +53,7 @@ void assignRefereeSuccess() { when(matchRepository.findByIdForUpdate(10L)).thenReturn(Optional.of(match)); when(volunteerRepository.findByIdForUpdate(20L)).thenReturn(Optional.of(referee)); when(matchRepository.findOverlappingAssignments( - referee, match.getStartTime(), match.getEndTime(), match.getId())).thenReturn(List.of()); + referee, match.getStartTime(), match.getEndTime(), match.getId())).thenReturn(List.of()); when(matchRepository.save(any(Match.class))).thenAnswer(invocation -> invocation.getArgument(0)); Match result = service.assignReferee("10", "20"); @@ -67,7 +67,7 @@ void assignRefereeFailsWhenMatchNotFound() { when(matchRepository.findByIdForUpdate(10L)).thenReturn(Optional.empty()); MatchAssignmentException ex = assertThrows( - MatchAssignmentException.class, () -> service.assignReferee("10", "20")); + MatchAssignmentException.class, () -> service.assignReferee("10", "20")); assertEquals(MatchAssignmentErrorCode.MATCH_NOT_FOUND, ex.getErrorCode()); } @@ -79,7 +79,7 @@ void assignRefereeFailsWhenRefereeNotFound() { when(volunteerRepository.findByIdForUpdate(20L)).thenReturn(Optional.empty()); MatchAssignmentException ex = assertThrows( - MatchAssignmentException.class, () -> service.assignReferee("10", "20")); + MatchAssignmentException.class, () -> service.assignReferee("10", "20")); assertEquals(MatchAssignmentErrorCode.REFEREE_NOT_FOUND, ex.getErrorCode()); } @@ -87,14 +87,14 @@ void assignRefereeFailsWhenRefereeNotFound() { @Test void assignRefereeFailsWhenVolunteerIsNotReferee() { Match match = buildMatch(10L, MatchState.SCHEDULED, null); - Floater floater = new Floater(); + Floater floater = Floater.create("Name", "mail@mail.com", "123456789", "STU123"); floater.setId(20L); when(matchRepository.findByIdForUpdate(10L)).thenReturn(Optional.of(match)); when(volunteerRepository.findByIdForUpdate(20L)).thenReturn(Optional.of(floater)); MatchAssignmentException ex = assertThrows( - MatchAssignmentException.class, () -> service.assignReferee("10", "20")); + MatchAssignmentException.class, () -> service.assignReferee("10", "20")); assertEquals(MatchAssignmentErrorCode.INVALID_ROLE, ex.getErrorCode()); } @@ -108,10 +108,10 @@ void assignRefereeFailsWhenAvailabilityConflict() { when(matchRepository.findByIdForUpdate(10L)).thenReturn(Optional.of(match)); when(volunteerRepository.findByIdForUpdate(20L)).thenReturn(Optional.of(referee)); when(matchRepository.findOverlappingAssignments( - referee, match.getStartTime(), match.getEndTime(), match.getId())).thenReturn(List.of(overlapping)); + referee, match.getStartTime(), match.getEndTime(), match.getId())).thenReturn(List.of(overlapping)); MatchAssignmentException ex = assertThrows( - MatchAssignmentException.class, () -> service.assignReferee("10", "20")); + MatchAssignmentException.class, () -> service.assignReferee("10", "20")); assertEquals(MatchAssignmentErrorCode.AVAILABILITY_CONFLICT, ex.getErrorCode()); } @@ -124,7 +124,7 @@ void assignRefereeFailsWhenMatchAlreadyHasReferee() { when(matchRepository.findByIdForUpdate(10L)).thenReturn(Optional.of(match)); MatchAssignmentException ex = assertThrows( - MatchAssignmentException.class, () -> service.assignReferee("10", "20")); + MatchAssignmentException.class, () -> service.assignReferee("10", "20")); assertEquals(MatchAssignmentErrorCode.MATCH_ALREADY_HAS_REFEREE, ex.getErrorCode()); } @@ -135,7 +135,7 @@ void assignRefereeFailsWhenMatchStateIsInvalid() { when(matchRepository.findByIdForUpdate(10L)).thenReturn(Optional.of(match)); MatchAssignmentException ex = assertThrows( - MatchAssignmentException.class, () -> service.assignReferee("10", "20")); + MatchAssignmentException.class, () -> service.assignReferee("10", "20")); assertEquals(MatchAssignmentErrorCode.INVALID_MATCH_STATE, ex.getErrorCode()); } @@ -143,7 +143,7 @@ void assignRefereeFailsWhenMatchStateIsInvalid() { @Test void assignRefereeFailsWhenMatchIdIsInvalidFormat() { MatchAssignmentException ex = assertThrows( - MatchAssignmentException.class, () -> service.assignReferee("abc", "20")); + MatchAssignmentException.class, () -> service.assignReferee("abc", "20")); assertEquals(MatchAssignmentErrorCode.INVALID_ID_FORMAT, ex.getErrorCode()); } @@ -168,13 +168,13 @@ void assignBatchSuccess() { when(volunteerRepository.findByIdForUpdate(20L)).thenReturn(Optional.of(refereeA)); when(volunteerRepository.findByIdForUpdate(21L)).thenReturn(Optional.of(refereeB)); when(matchRepository.findOverlappingAssignments(refereeA, matchA.getStartTime(), matchA.getEndTime(), 10L)) - .thenReturn(List.of()); + .thenReturn(List.of()); when(matchRepository.findOverlappingAssignments(refereeB, matchB.getStartTime(), matchB.getEndTime(), 11L)) - .thenReturn(List.of()); + .thenReturn(List.of()); BatchMatchAssignmentResponse response = service.assignBatch("3", List.of( - new BatchMatchAssignmentItemRequest("10", "20"), - new BatchMatchAssignmentItemRequest("11", "21"))); + new BatchMatchAssignmentItemRequest("10", "20"), + new BatchMatchAssignmentItemRequest("11", "21"))); assertEquals("3", response.roundId()); assertEquals("ASSIGNED", response.status()); @@ -203,16 +203,16 @@ void assignBatchFailsWhenPayloadHasIntraBatchConflictAndPersistsNone() { when(matchRepository.findByIdForUpdate(11L)).thenReturn(Optional.of(matchB)); when(volunteerRepository.findByIdForUpdate(20L)).thenReturn(Optional.of(referee)); when(matchRepository.findOverlappingAssignments(referee, matchA.getStartTime(), matchA.getEndTime(), 10L)) - .thenReturn(List.of()); + .thenReturn(List.of()); when(matchRepository.findOverlappingAssignments(referee, matchB.getStartTime(), matchB.getEndTime(), 11L)) - .thenReturn(List.of()); + .thenReturn(List.of()); List assignments = List.of( - new BatchMatchAssignmentItemRequest("10", "20"), - new BatchMatchAssignmentItemRequest("11", "20")); + new BatchMatchAssignmentItemRequest("10", "20"), + new BatchMatchAssignmentItemRequest("11", "20")); MatchAssignmentException ex = assertThrows( - MatchAssignmentException.class, - () -> service.assignBatch("3", assignments)); + MatchAssignmentException.class, + () -> service.assignBatch("3", assignments)); assertEquals(MatchAssignmentErrorCode.AVAILABILITY_CONFLICT, ex.getErrorCode()); assertEquals(1, ex.getIndex()); @@ -227,7 +227,7 @@ void assignBatchFailsWhenOneVolunteerIsNotRefereeAndPersistsNone() { Match matchB = buildMatch(11L, MatchState.SCHEDULED, null); matchB.setRound(round); Referee referee = buildReferee(20L); - Floater floater = new Floater(); + Floater floater = Floater.create("name", "email@email.com", "123456789", "STU123"); floater.setId(21L); when(roundRepository.findById(3L)).thenReturn(Optional.of(round)); @@ -236,14 +236,14 @@ void assignBatchFailsWhenOneVolunteerIsNotRefereeAndPersistsNone() { when(volunteerRepository.findByIdForUpdate(20L)).thenReturn(Optional.of(referee)); when(volunteerRepository.findByIdForUpdate(21L)).thenReturn(Optional.of(floater)); when(matchRepository.findOverlappingAssignments(referee, matchA.getStartTime(), matchA.getEndTime(), 10L)) - .thenReturn(List.of()); + .thenReturn(List.of()); List assignments = List.of( - new BatchMatchAssignmentItemRequest("10", "20"), - new BatchMatchAssignmentItemRequest("11", "21")); + new BatchMatchAssignmentItemRequest("10", "20"), + new BatchMatchAssignmentItemRequest("11", "21")); MatchAssignmentException ex = assertThrows( - MatchAssignmentException.class, - () -> service.assignBatch("3", assignments)); + MatchAssignmentException.class, + () -> service.assignBatch("3", assignments)); assertEquals(MatchAssignmentErrorCode.INVALID_ROLE, ex.getErrorCode()); assertEquals(1, ex.getIndex()); @@ -254,11 +254,11 @@ void assignBatchFailsWhenOneVolunteerIsNotRefereeAndPersistsNone() { void assignBatchFailsWhenItemIdFormatIsInvalid() { when(roundRepository.findById(3L)).thenReturn(Optional.of(buildRound(3L))); List assignments = List.of( - new BatchMatchAssignmentItemRequest("not-a-number", "20")); + new BatchMatchAssignmentItemRequest("not-a-number", "20")); MatchAssignmentException ex = assertThrows( - MatchAssignmentException.class, - () -> service.assignBatch("3", assignments)); + MatchAssignmentException.class, + () -> service.assignBatch("3", assignments)); assertEquals(MatchAssignmentErrorCode.INVALID_ID_FORMAT, ex.getErrorCode()); assertEquals(0, ex.getIndex()); @@ -269,12 +269,12 @@ void assignBatchFailsWhenItemIdFormatIsInvalid() { void assignBatchFailsWhenMatchIdAppearsTwiceInPayload() { when(roundRepository.findById(3L)).thenReturn(Optional.of(buildRound(3L))); List assignments = List.of( - new BatchMatchAssignmentItemRequest("10", "20"), - new BatchMatchAssignmentItemRequest("10", "21")); + new BatchMatchAssignmentItemRequest("10", "20"), + new BatchMatchAssignmentItemRequest("10", "21")); MatchAssignmentException ex = assertThrows( - MatchAssignmentException.class, - () -> service.assignBatch("3", assignments)); + MatchAssignmentException.class, + () -> service.assignBatch("3", assignments)); assertEquals(MatchAssignmentErrorCode.DUPLICATE_MATCH_IN_BATCH, ex.getErrorCode()); assertEquals(1, ex.getIndex()); @@ -285,11 +285,11 @@ void assignBatchFailsWhenMatchIdAppearsTwiceInPayload() { void assignBatchFailsWhenRoundDoesNotExist() { when(roundRepository.findById(3L)).thenReturn(Optional.empty()); List assignments = List.of( - new BatchMatchAssignmentItemRequest("10", "20")); + new BatchMatchAssignmentItemRequest("10", "20")); MatchAssignmentException ex = assertThrows( - MatchAssignmentException.class, - () -> service.assignBatch("3", assignments)); + MatchAssignmentException.class, + () -> service.assignBatch("3", assignments)); assertEquals(MatchAssignmentErrorCode.ROUND_NOT_FOUND, ex.getErrorCode()); verify(matchRepository, never()).saveAll(any()); @@ -306,7 +306,7 @@ private Match buildMatch(Long id, MatchState state, Referee referee) { } private Referee buildReferee(Long id) { - Referee referee = new Referee(); + Referee referee = Referee.create("Referee" + id, "referee" + id + "@mail.com", "123456789"); referee.setId(id); return referee; } diff --git a/src/test/java/cat/udl/eps/softarch/fll/service/MatchScoreRegistrationServiceTest.java b/src/test/java/cat/udl/eps/softarch/fll/service/MatchScoreRegistrationServiceTest.java index 1b874d18..52f2db9a 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/service/MatchScoreRegistrationServiceTest.java +++ b/src/test/java/cat/udl/eps/softarch/fll/service/MatchScoreRegistrationServiceTest.java @@ -1,15 +1,10 @@ package cat.udl.eps.softarch.fll.service; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import java.time.LocalTime; -import java.util.List; -import java.util.Optional; +import cat.udl.eps.softarch.fll.domain.Match; +import cat.udl.eps.softarch.fll.domain.MatchResult; +import cat.udl.eps.softarch.fll.domain.Team; +import cat.udl.eps.softarch.fll.repository.MatchRepository; +import cat.udl.eps.softarch.fll.repository.MatchResultRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -19,11 +14,16 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.dao.DataIntegrityViolationException; -import cat.udl.eps.softarch.fll.domain.Match; -import cat.udl.eps.softarch.fll.domain.MatchResult; -import cat.udl.eps.softarch.fll.domain.Team; -import cat.udl.eps.softarch.fll.repository.MatchRepository; -import cat.udl.eps.softarch.fll.repository.MatchResultRepository; +import java.time.LocalTime; +import java.util.List; +import java.util.Optional; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class MatchScoreRegistrationServiceTest { @@ -52,8 +52,8 @@ class MatchScoreRegistrationServiceTest { @BeforeEach void setUp() { - Team teamA = new Team("Team-A"); - Team teamB = new Team("Team-B"); + Team teamA = Team.create("Team-A", "City-A", 2000, "Junior"); + Team teamB = Team.create("Team-B", "City-A", 2000, "Junior"); match = new Match(); match.setId(1L); @@ -92,8 +92,8 @@ void registerMatchScoreShouldThrowMatchNotFoundWhenMatchDoesNotExist() { when(matchRepository.findById(1L)).thenReturn(Optional.empty()); MatchScoreRegistrationService.RegistrationException ex = assertThrows( - MatchScoreRegistrationService.RegistrationException.class, - () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); + MatchScoreRegistrationService.RegistrationException.class, + () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); assertEquals(MatchScoreRegistrationService.ErrorCode.MATCH_NOT_FOUND, ex.getErrorCode()); verify(matchResultRepository, never()).saveAllAndFlush(any()); @@ -106,8 +106,8 @@ void registerMatchScoreShouldThrowInvalidMatchStateWhenMatchHasNoStartTime() { when(matchRepository.findById(1L)).thenReturn(Optional.of(match)); MatchScoreRegistrationService.RegistrationException ex = assertThrows( - MatchScoreRegistrationService.RegistrationException.class, - () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); + MatchScoreRegistrationService.RegistrationException.class, + () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); assertEquals(MatchScoreRegistrationService.ErrorCode.INVALID_MATCH_STATE, ex.getErrorCode()); verify(matchResultRepository, never()).saveAllAndFlush(any()); @@ -120,8 +120,8 @@ void registerMatchScoreShouldThrowMatchNotFinishedWhenMatchHasNoEndTime() { when(matchRepository.findById(1L)).thenReturn(Optional.of(match)); MatchScoreRegistrationService.RegistrationException ex = assertThrows( - MatchScoreRegistrationService.RegistrationException.class, - () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); + MatchScoreRegistrationService.RegistrationException.class, + () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); assertEquals(MatchScoreRegistrationService.ErrorCode.MATCH_NOT_FINISHED, ex.getErrorCode()); verify(matchResultRepository, never()).saveAllAndFlush(any()); @@ -134,8 +134,8 @@ void registerMatchScoreShouldThrowResultAlreadyExistsWhenMatchAlreadyHasResults( when(matchResultRepository.existsByMatch(match)).thenReturn(true); MatchScoreRegistrationService.RegistrationException ex = assertThrows( - MatchScoreRegistrationService.RegistrationException.class, - () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); + MatchScoreRegistrationService.RegistrationException.class, + () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); assertEquals(MatchScoreRegistrationService.ErrorCode.RESULT_ALREADY_EXISTS, ex.getErrorCode()); verify(matchResultRepository, never()).saveAllAndFlush(any()); @@ -149,8 +149,8 @@ void registerMatchScoreShouldThrowResultAlreadyExistsWhenConcurrentInsertViolate when(matchResultRepository.saveAllAndFlush(any())).thenThrow(new DataIntegrityViolationException("duplicate")); MatchScoreRegistrationService.RegistrationException ex = assertThrows( - MatchScoreRegistrationService.RegistrationException.class, - () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); + MatchScoreRegistrationService.RegistrationException.class, + () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); assertEquals(MatchScoreRegistrationService.ErrorCode.RESULT_ALREADY_EXISTS, ex.getErrorCode()); verify(rankingService, never()).recalculateRanking(); @@ -163,8 +163,8 @@ void registerMatchScoreShouldThrowInvalidScoreWhenScoreIsNegative() { when(matchResultRepository.existsByMatch(match)).thenReturn(false); MatchScoreRegistrationService.RegistrationException ex = assertThrows( - MatchScoreRegistrationService.RegistrationException.class, - () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); + MatchScoreRegistrationService.RegistrationException.class, + () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); assertEquals(MatchScoreRegistrationService.ErrorCode.INVALID_SCORE, ex.getErrorCode()); verify(matchResultRepository, never()).saveAllAndFlush(any()); @@ -176,8 +176,8 @@ void registerMatchScoreShouldThrowInvalidScoreWhenScoreIsNull() { teamBScore = null; MatchScoreRegistrationService.RegistrationException ex = assertThrows( - MatchScoreRegistrationService.RegistrationException.class, - () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); + MatchScoreRegistrationService.RegistrationException.class, + () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); assertEquals(MatchScoreRegistrationService.ErrorCode.INVALID_SCORE_PAYLOAD, ex.getErrorCode()); verify(matchResultRepository, never()).saveAllAndFlush(any()); @@ -191,8 +191,8 @@ void registerMatchScoreShouldThrowTeamMismatchWhenTeamsDoNotMatchAssignedTeams() when(matchResultRepository.existsByMatch(match)).thenReturn(false); MatchScoreRegistrationService.RegistrationException ex = assertThrows( - MatchScoreRegistrationService.RegistrationException.class, - () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); + MatchScoreRegistrationService.RegistrationException.class, + () -> matchScoreRegistrationService.registerMatchScore(matchId, teamAId, teamBId, teamAScore, teamBScore)); assertEquals(MatchScoreRegistrationService.ErrorCode.TEAM_MISMATCH, ex.getErrorCode()); verify(matchResultRepository, never()).saveAllAndFlush(any()); @@ -215,6 +215,6 @@ void registerMatchScoreShouldSupportSwappedTeamOrderInInputPayload() { assertEquals(80, savedResults.get(0).getScore()); assertEquals(40, savedResults.get(1).getScore()); - assertFalse(savedResults.get(0).getTeam().getId().equals(savedResults.get(1).getTeam().getId())); + assertNotEquals(savedResults.get(0).getTeam().getId(), savedResults.get(1).getTeam().getId()); } } diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/AssignCoachStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/AssignCoachStepDefs.java index 39d5cb4e..99a8ea6b 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/AssignCoachStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/AssignCoachStepDefs.java @@ -1,35 +1,31 @@ package cat.udl.eps.softarch.fll.steps; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; - -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; - -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.ResultActions; - -import com.fasterxml.jackson.databind.ObjectMapper; - import cat.udl.eps.softarch.fll.domain.Coach; import cat.udl.eps.softarch.fll.domain.Team; import cat.udl.eps.softarch.fll.repository.CoachRepository; import cat.udl.eps.softarch.fll.repository.TeamRepository; import io.cucumber.java.Before; -import io.cucumber.java.en.*; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.ResultActions; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; public class AssignCoachStepDefs { - private StepDefs stepDefs; - private TeamRepository teamRepository; - private CoachRepository coachRepository; - private ObjectMapper mapper; + private final StepDefs stepDefs; + private final TeamRepository teamRepository; + private final CoachRepository coachRepository; - private Map teamIdMap = new HashMap<>(); - private Map coachIdMap = new HashMap<>(); + private final Map teamIdMap = new HashMap<>(); + private final Map coachIdMap = new HashMap<>(); public AssignCoachStepDefs(StepDefs stepDefs, TeamRepository teamRepository, @@ -37,7 +33,6 @@ public AssignCoachStepDefs(StepDefs stepDefs, this.stepDefs = stepDefs; this.teamRepository = teamRepository; this.coachRepository = coachRepository; - this.mapper = new ObjectMapper(); } @@ -59,11 +54,7 @@ private ResultActions performAssignCoach(String teamId, Integer coachId) throws @Given("a team {string} exists") public void aTeamExists(String teamName) { - Team team = new Team(); - team.setName(teamName); - team.setCity("Lleida"); - team.setFoundationYear(2020); - team.setCategory("FLL"); + Team team = Team.create(teamName, "Lleida", 2020, "FLL"); team.setEducationalCenter("School"); teamRepository.save(team); teamIdMap.put(teamName, team.getId()); @@ -103,8 +94,8 @@ public void errorReturned(String error) throws Exception { int expectedStatus = switch (error) { case "TEAM_NOT_FOUND", "COACH_NOT_FOUND" -> 404; case "COACH_ALREADY_ASSIGNED", - "MAX_COACHES_PER_TEAM_REACHED", - "MAX_TEAMS_PER_COACH_REACHED" -> 409; + "MAX_COACHES_PER_TEAM_REACHED", + "MAX_TEAMS_PER_COACH_REACHED" -> 409; default -> 400; }; diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/CompetitionTableStepsDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/CompetitionTableStepsDefs.java index b1e1eccc..a8c43db2 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/CompetitionTableStepsDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/CompetitionTableStepsDefs.java @@ -1,13 +1,13 @@ package cat.udl.eps.softarch.fll.steps; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; import cat.udl.eps.softarch.fll.domain.CompetitionTable; import cat.udl.eps.softarch.fll.domain.Referee; import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; public class CompetitionTableStepsDefs { @@ -24,7 +24,7 @@ public void a_new_competition_table_with_id(String tableId) { @When("I add a referee named {string} to the table") public void i_add_a_referee_named_to_the_table(String name) { - namedReferee = new Referee(); + namedReferee = Referee.create(name, "test@gmail.com", "123456789"); namedRefereeName = name; table.addReferee(namedReferee); } @@ -32,7 +32,7 @@ public void i_add_a_referee_named_to_the_table(String name) { @Then("the table should have {int} referee") public void the_table_should_have_referee(Integer expectedCount) { assertEquals(expectedCount, table.getReferees().size(), - "The table does not have the expected number of referees"); + "The table does not have the expected number of referees"); } @Then("the referee {string} should be supervising {string}") @@ -41,19 +41,22 @@ public void the_referee_should_be_supervising(String refereeName, String expecte assertNotNull(namedReferee.getSupervisesTable(), "The referee is not assigned to any table"); assertEquals(expectedTableId, namedReferee.getSupervisesTable().getId(), - "The referee is assigned to the wrong table"); + "The referee is assigned to the wrong table"); } @Given("the table already has {int} referees") public void the_table_already_has_referees(Integer count) { for (int i = 0; i < count; i++) { - table.addReferee(new Referee()); + Referee referee = Referee.create("Referee" + i, "pep@gmail.com", "123456789"); + referee.setId(i + 1L); + table.addReferee(referee); } } @When("I try to add another referee to the table") public void i_try_to_add_another_referee_to_the_table() { - Referee extraReferee = new Referee(); + Referee extraReferee = Referee.create("Another Referee", "pep@gmail.com", "123456789"); + extraReferee.setId(10000L); try { table.addReferee(extraReferee); } catch (Exception e) { @@ -64,8 +67,7 @@ public void i_try_to_add_another_referee_to_the_table() { @Then("the validation should prevent adding a 4th referee") public void the_validation_should_prevent_adding_a_4th_referee() { assertNotNull(thrownException, "An exception should have been thrown when adding the 4th referee"); - assertTrue(thrownException instanceof IllegalStateException, - "The exception should be an IllegalStateException"); + assertInstanceOf(IllegalStateException.class, thrownException, "The exception should be an IllegalStateException"); assertEquals("A table can have a maximum of 3 referees", thrownException.getMessage()); assertEquals(3, table.getReferees().size(), "The table should strictly contain 3 referees"); } diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/EditionCompetitionTableStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/EditionCompetitionTableStepDefs.java index de6da7d2..0ffdc285 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/EditionCompetitionTableStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/EditionCompetitionTableStepDefs.java @@ -1,13 +1,5 @@ package cat.udl.eps.softarch.fll.steps; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.not; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import java.time.LocalTime; -import java.util.UUID; -import org.springframework.http.MediaType; import cat.udl.eps.softarch.fll.domain.CompetitionTable; import cat.udl.eps.softarch.fll.domain.Edition; import cat.udl.eps.softarch.fll.domain.Match; @@ -20,6 +12,14 @@ import io.cucumber.java.en.And; import io.cucumber.java.en.Given; import io.cucumber.java.en.When; +import org.springframework.http.MediaType; +import java.time.LocalTime; +import java.util.UUID; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.not; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; public class EditionCompetitionTableStepDefs { @@ -34,11 +34,11 @@ public class EditionCompetitionTableStepDefs { private String otherEditionTableIdentifier; public EditionCompetitionTableStepDefs( - StepDefs stepDefs, - EditionRepository editionRepository, - RoundRepository roundRepository, - MatchRepository matchRepository, - CompetitionTableRepository competitionTableRepository) { + StepDefs stepDefs, + EditionRepository editionRepository, + RoundRepository roundRepository, + MatchRepository matchRepository, + CompetitionTableRepository competitionTableRepository) { this.stepDefs = stepDefs; this.editionRepository = editionRepository; this.roundRepository = roundRepository; @@ -108,7 +108,7 @@ public void iRequestCompetitionTablesForTheTargetEdition() throws Exception { stepDefs.result = stepDefs.mockMvc.perform(get("/editions/{editionId}/tables", targetEditionId) .accept(MediaType.APPLICATION_JSON) .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .andDo(print()); } @When("I request competition tables for edition id {long}") @@ -116,7 +116,7 @@ public void iRequestCompetitionTablesForEditionId(long editionId) throws Excepti stepDefs.result = stepDefs.mockMvc.perform(get("/editions/{editionId}/tables", editionId) .accept(MediaType.APPLICATION_JSON) .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .andDo(print()); } @And("the competition table overview contains {int} table with {int} matches") @@ -140,8 +140,8 @@ public void theCompetitionTableOverviewDoesNotIncludeTablesFromOtherEditions() t @And("the competition table overview includes match times {string} and {string}") public void theCompetitionTableOverviewIncludesMatchTimes(String startTime, String endTime) throws Exception { stepDefs.result - .andExpect(jsonPath("$[0].matches[0].startTime").value(startTime)) - .andExpect(jsonPath("$[0].matches[0].endTime").value(endTime)); + .andExpect(jsonPath("$[0].matches[0].startTime").value(startTime)) + .andExpect(jsonPath("$[0].matches[0].endTime").value(endTime)); } @And("the competition table overview error is {string}") @@ -150,10 +150,7 @@ public void theCompetitionTableOverviewErrorIs(String error) throws Exception { } private Edition createEdition(String prefix) { - Edition edition = new Edition(); - edition.setYear(2026); - edition.setVenueName(prefix + " " + UUID.randomUUID()); - edition.setDescription(prefix); + Edition edition = Edition.create(2026, prefix + " " + UUID.randomUUID(), prefix); return editionRepository.save(edition); } diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/EditionVolunteerStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/EditionVolunteerStepDefs.java index 628dc30d..79b7bc6e 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/EditionVolunteerStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/EditionVolunteerStepDefs.java @@ -1,12 +1,5 @@ package cat.udl.eps.softarch.fll.steps; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.not; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import java.util.UUID; -import org.springframework.http.MediaType; import cat.udl.eps.softarch.fll.domain.Edition; import cat.udl.eps.softarch.fll.domain.Floater; import cat.udl.eps.softarch.fll.domain.Judge; @@ -18,6 +11,13 @@ import io.cucumber.java.en.And; import io.cucumber.java.en.Given; import io.cucumber.java.en.When; +import org.springframework.http.MediaType; +import java.util.UUID; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.not; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; public class EditionVolunteerStepDefs { @@ -33,11 +33,11 @@ public class EditionVolunteerStepDefs { private String otherFloaterName; public EditionVolunteerStepDefs( - StepDefs stepDefs, - EditionRepository editionRepository, - RefereeRepository refereeRepository, - JudgeRepository judgeRepository, - FloaterRepository floaterRepository) { + StepDefs stepDefs, + EditionRepository editionRepository, + RefereeRepository refereeRepository, + JudgeRepository judgeRepository, + FloaterRepository floaterRepository) { this.stepDefs = stepDefs; this.editionRepository = editionRepository; this.refereeRepository = refereeRepository; @@ -53,50 +53,30 @@ public void anEditionVolunteerOverviewDatasetExists() { String suffix = UUID.randomUUID().toString().substring(0, 8); - Referee targetReferee = new Referee(); - targetReferee.setName("Target Referee " + suffix); - targetReferee.setEmailAddress("target.ref." + suffix + "@example.com"); - targetReferee.setPhoneNumber("111111111"); + Referee targetReferee = Referee.create("Target Referee " + suffix, "target.ref." + suffix + "@example.com", "111111111"); targetReferee.setEdition(targetEdition); refereeRepository.save(targetReferee); - Judge targetJudge = new Judge(); - targetJudge.setName("Target Judge " + suffix); - targetJudge.setEmailAddress("target.judge." + suffix + "@example.com"); - targetJudge.setPhoneNumber("222222222"); + Judge targetJudge = Judge.create("Target Judge " + suffix, "target.judge." + suffix + "@example.com", "222222222"); targetJudge.setEdition(targetEdition); judgeRepository.save(targetJudge); - Floater targetFloater = new Floater(); - targetFloater.setName("Target Floater " + suffix); - targetFloater.setEmailAddress("target.floater." + suffix + "@example.com"); - targetFloater.setPhoneNumber("333333333"); - targetFloater.setStudentCode("TARGET-" + suffix); + Floater targetFloater = Floater.create("Target Floater " + suffix, "target.floater." + suffix + "@example.com", "333333333", "TARGET-" + suffix); targetFloater.setEdition(targetEdition); floaterRepository.save(targetFloater); otherRefereeName = "Other Referee " + suffix; - Referee otherReferee = new Referee(); - otherReferee.setName(otherRefereeName); - otherReferee.setEmailAddress("other.ref." + suffix + "@example.com"); - otherReferee.setPhoneNumber("444444444"); + Referee otherReferee = Referee.create(otherRefereeName, "other.ref." + suffix + "@example.com", "444444444"); otherReferee.setEdition(otherEdition); refereeRepository.save(otherReferee); otherJudgeName = "Other Judge " + suffix; - Judge otherJudge = new Judge(); - otherJudge.setName(otherJudgeName); - otherJudge.setEmailAddress("other.judge." + suffix + "@example.com"); - otherJudge.setPhoneNumber("555555555"); + Judge otherJudge = Judge.create(otherJudgeName, "other.judge." + suffix + "@example.com", "555555555"); otherJudge.setEdition(otherEdition); judgeRepository.save(otherJudge); otherFloaterName = "Other Floater " + suffix; - Floater otherFloater = new Floater(); - otherFloater.setName(otherFloaterName); - otherFloater.setEmailAddress("other.floater." + suffix + "@example.com"); - otherFloater.setPhoneNumber("666666666"); - otherFloater.setStudentCode("OTHER-" + suffix); + Floater otherFloater = Floater.create(otherFloaterName, "other.floater." + suffix + "@example.com", "666666666", "OTHER-" + suffix); otherFloater.setEdition(otherEdition); floaterRepository.save(otherFloater); } @@ -112,7 +92,7 @@ public void iRequestVolunteersGroupedByTypeForTheTargetEdition() throws Exceptio stepDefs.result = stepDefs.mockMvc.perform(get("/editions/{editionId}/volunteers", targetEditionId) .accept(MediaType.APPLICATION_JSON) .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .andDo(print()); } @When("I request volunteers grouped by type for edition id {long}") @@ -120,23 +100,23 @@ public void iRequestVolunteersGroupedByTypeForEditionId(long editionId) throws E stepDefs.result = stepDefs.mockMvc.perform(get("/editions/{editionId}/volunteers", editionId) .accept(MediaType.APPLICATION_JSON) .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .andDo(print()); } @And("the volunteer overview contains {int} referee {int} judge and {int} floater") public void theVolunteerOverviewContainsRefereeJudgeAndFloater(int referees, int judges, int floaters) throws Exception { stepDefs.result - .andExpect(jsonPath("$.referees.length()").value(referees)) - .andExpect(jsonPath("$.judges.length()").value(judges)) - .andExpect(jsonPath("$.floaters.length()").value(floaters)); + .andExpect(jsonPath("$.referees.length()").value(referees)) + .andExpect(jsonPath("$.judges.length()").value(judges)) + .andExpect(jsonPath("$.floaters.length()").value(floaters)); } @And("the volunteer overview does not include volunteers from other editions") public void theVolunteerOverviewDoesNotIncludeVolunteersFromOtherEditions() throws Exception { stepDefs.result - .andExpect(jsonPath("$.referees[*].name", not(hasItem(otherRefereeName)))) - .andExpect(jsonPath("$.judges[*].name", not(hasItem(otherJudgeName)))) - .andExpect(jsonPath("$.floaters[*].name", not(hasItem(otherFloaterName)))); + .andExpect(jsonPath("$.referees[*].name", not(hasItem(otherRefereeName)))) + .andExpect(jsonPath("$.judges[*].name", not(hasItem(otherJudgeName)))) + .andExpect(jsonPath("$.floaters[*].name", not(hasItem(otherFloaterName)))); } @And("the volunteer overview error is {string}") @@ -145,10 +125,7 @@ public void theVolunteerOverviewErrorIs(String error) throws Exception { } private Edition createEdition(String venueName, String description) { - Edition edition = new Edition(); - edition.setYear(2026); - edition.setVenueName(venueName + " " + UUID.randomUUID()); - edition.setDescription(description); + Edition edition = Edition.create(2026, venueName + " " + UUID.randomUUID(), description); return editionRepository.save(edition); } } diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/JudgeSearchStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/JudgeSearchStepDefs.java index 4a2dda7b..428ff473 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/JudgeSearchStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/JudgeSearchStepDefs.java @@ -1,18 +1,18 @@ package cat.udl.eps.softarch.fll.steps; -import static org.hamcrest.Matchers.hasItem; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import com.fasterxml.jackson.databind.JsonNode; -import java.util.UUID; -import org.springframework.http.MediaType; import cat.udl.eps.softarch.fll.domain.Judge; import cat.udl.eps.softarch.fll.repository.JudgeRepository; +import com.fasterxml.jackson.databind.JsonNode; import io.cucumber.java.en.And; import io.cucumber.java.en.Given; import io.cucumber.java.en.When; +import org.springframework.http.MediaType; +import java.util.UUID; +import static org.hamcrest.Matchers.hasItem; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; public class JudgeSearchStepDefs { @@ -29,16 +29,10 @@ public void judgesExistWithNames(String firstJudgeName, String secondJudgeName) judgeRepository.deleteAll(); String suffix = UUID.randomUUID().toString().substring(0, 8); - Judge firstJudge = new Judge(); - firstJudge.setName(firstJudgeName); - firstJudge.setEmailAddress("judge.search.first." + suffix + "@example.com"); - firstJudge.setPhoneNumber("111111111"); + Judge firstJudge = Judge.create(firstJudgeName, "judge.search.first." + suffix + "@example.com", "111111111"); judgeRepository.save(firstJudge); - Judge secondJudge = new Judge(); - secondJudge.setName(secondJudgeName); - secondJudge.setEmailAddress("judge.search.second." + suffix + "@example.com"); - secondJudge.setPhoneNumber("222222222"); + Judge secondJudge = Judge.create(secondJudgeName, "judge.search.second." + suffix + "@example.com", "222222222"); judgeRepository.save(secondJudge); } @@ -47,7 +41,7 @@ public void iSearchJudgesByNameContaining(String name) throws Exception { stepDefs.result = stepDefs.mockMvc.perform(get("/judges/search/findByNameContaining") .param("name", name) .accept(MediaType.APPLICATION_JSON)) - .andDo(print()); + .andDo(print()); } @And("^the judges search response should contain (\\d+) result[s]?$") diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/LeaderboardStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/LeaderboardStepDefs.java index 2f44cf45..7dc4a13a 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/LeaderboardStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/LeaderboardStepDefs.java @@ -1,14 +1,5 @@ package cat.udl.eps.softarch.fll.steps; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import java.time.LocalDate; -import java.time.LocalTime; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicInteger; -import org.springframework.http.MediaType; import cat.udl.eps.softarch.fll.domain.Edition; import cat.udl.eps.softarch.fll.domain.Match; import cat.udl.eps.softarch.fll.domain.MatchResult; @@ -22,6 +13,15 @@ import io.cucumber.java.en.And; import io.cucumber.java.en.Given; import io.cucumber.java.en.When; +import org.springframework.http.MediaType; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; public class LeaderboardStepDefs { private static final AtomicInteger ROUND_NUMBER_SEQUENCE = new AtomicInteger(10000); @@ -32,16 +32,15 @@ public class LeaderboardStepDefs { private final MatchRepository matchRepository; private final MatchResultRepository matchResultRepository; private final TeamRepository teamRepository; - - private Long currentEditionId; private final Map teamNameByAlias = new HashMap<>(); + private Long currentEditionId; public LeaderboardStepDefs(StepDefs stepDefs, - EditionRepository editionRepository, - RoundRepository roundRepository, - MatchRepository matchRepository, - MatchResultRepository matchResultRepository, - TeamRepository teamRepository) { + EditionRepository editionRepository, + RoundRepository roundRepository, + MatchRepository matchRepository, + MatchResultRepository matchResultRepository, + TeamRepository teamRepository) { this.stepDefs = stepDefs; this.editionRepository = editionRepository; this.roundRepository = roundRepository; @@ -113,17 +112,17 @@ public void anEditionWithTieOnScoreAndMatchesPlayedExists() { @When("I request leaderboard for that edition with page {int} and size {int}") public void iRequestLeaderboardForThatEditionWithPagination(int page, int size) throws Exception { stepDefs.result = stepDefs.mockMvc.perform(get("/leaderboards/editions/" + currentEditionId) - .param("page", String.valueOf(page)) - .param("size", String.valueOf(size)) - .accept(MediaType.APPLICATION_JSON)); + .param("page", String.valueOf(page)) + .param("size", String.valueOf(size)) + .accept(MediaType.APPLICATION_JSON)); } @When("I request leaderboard for non-existent edition {long} with page {int} and size {int}") public void iRequestLeaderboardForNonExistentEditionWithPagination(long editionId, int page, int size) throws Exception { stepDefs.result = stepDefs.mockMvc.perform(get("/leaderboards/editions/" + editionId) - .param("page", String.valueOf(page)) - .param("size", String.valueOf(size)) - .accept(MediaType.APPLICATION_JSON)); + .param("page", String.valueOf(page)) + .param("size", String.valueOf(size)) + .accept(MediaType.APPLICATION_JSON)); } @When("I request leaderboard for a non-existent edition with page {int} and size {int}") @@ -157,10 +156,11 @@ public void leaderboardItemAtIndexShouldHavePosition(int index, int position) th } private Edition createEdition() { - Edition edition = new Edition(); - edition.setYear(2025 + ((UUID.randomUUID().hashCode() & 0x7fffffff) % 1000)); - edition.setVenueName("Venue-" + UUID.randomUUID().toString().substring(0, 6)); - edition.setDescription("Leaderboard test edition"); + Edition edition = Edition.create( + 2025 + ((UUID.randomUUID().hashCode() & 0x7fffffff) % 1000), + "Venue-" + UUID.randomUUID().toString().substring(0, 6), + "Leaderboard test edition" + ); edition = editionRepository.save(edition); currentEditionId = edition.getId(); return edition; @@ -174,12 +174,8 @@ private Round createRoundForEdition(Edition edition) { } private Team createTeam(String teamAlias) { - Team team = new Team(); String teamName = teamAlias + "-" + UUID.randomUUID().toString().substring(0, 6); - team.setName(teamName); - team.setCity("Igualada"); - team.setFoundationYear(2000); - team.setCategory("Challenge"); + Team team = Team.create(teamName, "Igualada", 2000, "Challenge"); team.setEducationalCenter("EPS"); team.setInscriptionDate(LocalDate.now()); teamNameByAlias.put(teamAlias, teamName); @@ -196,10 +192,7 @@ private void createResult(Round round, Team team, int score) { match.setEndTime(LocalTime.of(11, 0)); match = matchRepository.save(match); - MatchResult result = new MatchResult(); - result.setMatch(match); - result.setTeam(team); - result.setScore(score); + MatchResult result = MatchResult.create(score, match, team); matchResultRepository.save(result); } } diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/ManageEditionStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/ManageEditionStepDefs.java index 585dea6b..8dc4c95a 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/ManageEditionStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/ManageEditionStepDefs.java @@ -1,5 +1,13 @@ package cat.udl.eps.softarch.fll.steps; +import cat.udl.eps.softarch.fll.domain.Edition; +import cat.udl.eps.softarch.fll.repository.EditionRepository; +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.When; +import org.springframework.http.MediaType; +import java.nio.charset.StandardCharsets; +import java.util.Map; import static org.hamcrest.Matchers.is; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -8,14 +16,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import java.nio.charset.StandardCharsets; -import java.util.Map; -import org.springframework.http.MediaType; -import cat.udl.eps.softarch.fll.domain.Edition; -import cat.udl.eps.softarch.fll.repository.EditionRepository; -import io.cucumber.java.en.And; -import io.cucumber.java.en.Given; -import io.cucumber.java.en.When; public class ManageEditionStepDefs { private final StepDefs stepDefs; @@ -29,19 +29,16 @@ public ManageEditionStepDefs(StepDefs stepDefs, EditionRepository editionReposit @When("I create a new edition with year {int}, venue {string} and description {string}") public void iCreateANewEdition(int year, String venue, String description) throws Exception { - Edition edition = new Edition(); - edition.setYear(year); - edition.setVenueName(venue); - edition.setDescription(description); + Edition edition = Edition.create(year, venue, description); stepDefs.result = stepDefs.mockMvc.perform( post("/editions") - .contentType(MediaType.APPLICATION_JSON) - .content(stepDefs.mapper.writeValueAsString(edition)) - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .contentType(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(edition)) + .characterEncoding(StandardCharsets.UTF_8) + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); editionUri = stepDefs.result.andReturn().getResponse().getHeader("Location"); } @@ -50,20 +47,17 @@ public void iCreateANewEdition(int year, String venue, String description) throw public void theEditionHasFields(int year, String venue, String description) throws Exception { stepDefs.result = stepDefs.mockMvc.perform( get(editionUri) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()) - .andExpect(jsonPath("$.year", is(year))) - .andExpect(jsonPath("$.venueName", is(venue))) - .andExpect(jsonPath("$.description", is(description))); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()) + .andExpect(jsonPath("$.year", is(year))) + .andExpect(jsonPath("$.venueName", is(venue))) + .andExpect(jsonPath("$.description", is(description))); } @Given("There is an edition with year {int}, venue {string} and description {string}") public void thereIsAnEdition(int year, String venue, String description) { - Edition edition = new Edition(); - edition.setYear(year); - edition.setVenueName(venue); - edition.setDescription(description); + Edition edition = Edition.create(year, venue, description); edition = editionRepository.save(edition); editionUri = "/editions/" + edition.getId(); } @@ -72,49 +66,49 @@ public void thereIsAnEdition(int year, String venue, String description) { public void iRetrieveTheEdition() throws Exception { stepDefs.result = stepDefs.mockMvc.perform( get(editionUri) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @When("I update the edition venue to {string}") public void iUpdateTheEditionVenue(String venue) throws Exception { stepDefs.result = stepDefs.mockMvc.perform( patch(editionUri) - .contentType(MediaType.APPLICATION_JSON) - .content(stepDefs.mapper.writeValueAsString(Map.of("venueName", venue))) - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .contentType(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(Map.of("venueName", venue))) + .characterEncoding(StandardCharsets.UTF_8) + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @And("The edition has venue {string}") public void theEditionHasVenue(String venue) throws Exception { stepDefs.result = stepDefs.mockMvc.perform( get(editionUri) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()) - .andExpect(jsonPath("$.venueName", is(venue))); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()) + .andExpect(jsonPath("$.venueName", is(venue))); } @When("I delete the edition") public void iDeleteTheEdition() throws Exception { stepDefs.result = stepDefs.mockMvc.perform( delete(editionUri) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @And("The edition has been deleted") public void theEditionHasBeenDeleted() throws Exception { stepDefs.mockMvc.perform( get(editionUri) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()) - .andExpect(status().isNotFound()); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()) + .andExpect(status().isNotFound()); } } diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/ManageMediaContentStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/ManageMediaContentStepDefs.java index 8148c710..be855ecc 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/ManageMediaContentStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/ManageMediaContentStepDefs.java @@ -1,5 +1,13 @@ package cat.udl.eps.softarch.fll.steps; +import cat.udl.eps.softarch.fll.domain.MediaContent; +import cat.udl.eps.softarch.fll.repository.MediaContentRepository; +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.When; +import org.springframework.http.MediaType; +import java.nio.charset.StandardCharsets; +import java.util.Map; import static org.hamcrest.Matchers.is; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -8,14 +16,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import java.nio.charset.StandardCharsets; -import java.util.Map; -import org.springframework.http.MediaType; -import cat.udl.eps.softarch.fll.domain.MediaContent; -import cat.udl.eps.softarch.fll.repository.MediaContentRepository; -import io.cucumber.java.en.And; -import io.cucumber.java.en.Given; -import io.cucumber.java.en.When; public class ManageMediaContentStepDefs { private final StepDefs stepDefs; @@ -29,18 +29,16 @@ public ManageMediaContentStepDefs(StepDefs stepDefs, MediaContentRepository medi @When("I create a new media content with url {string} and type {string}") public void iCreateANewMediaContent(String url, String type) throws Exception { - MediaContent mediaContent = new MediaContent(); - mediaContent.setUrl(url); - mediaContent.setType(type); + MediaContent mediaContent = MediaContent.create(url, type); stepDefs.result = stepDefs.mockMvc.perform( post("/mediaContents") - .contentType(MediaType.APPLICATION_JSON) - .content(stepDefs.mapper.writeValueAsString(mediaContent)) - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .contentType(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(mediaContent)) + .characterEncoding(StandardCharsets.UTF_8) + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); mediaContentUri = stepDefs.result.andReturn().getResponse().getHeader("Location"); } @@ -49,17 +47,15 @@ public void iCreateANewMediaContent(String url, String type) throws Exception { public void theCreatedMediaContentHasType(String type) throws Exception { stepDefs.result = stepDefs.mockMvc.perform( get(mediaContentUri) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()) - .andExpect(jsonPath("$.type", is(type))); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()) + .andExpect(jsonPath("$.type", is(type))); } @Given("There is a media content with url {string} and type {string}") public void thereIsAMediaContent(String url, String type) { - MediaContent mediaContent = new MediaContent(); - mediaContent.setUrl(url); - mediaContent.setType(type); + MediaContent mediaContent = MediaContent.create(url, type); mediaContentRepository.save(mediaContent); mediaContentUri = "/mediaContents/" + url; } @@ -69,9 +65,9 @@ public void iRetrieveTheMediaContent(String url) throws Exception { mediaContentUri = "/mediaContents/" + url; stepDefs.result = stepDefs.mockMvc.perform( get(mediaContentUri) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @When("I update the media content with url {string} type to {string}") @@ -79,40 +75,40 @@ public void iUpdateTheMediaContentType(String url, String type) throws Exception mediaContentUri = "/mediaContents/" + url; stepDefs.result = stepDefs.mockMvc.perform( patch(mediaContentUri) - .contentType(MediaType.APPLICATION_JSON) - .content(stepDefs.mapper.writeValueAsString(Map.of("type", type))) - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .contentType(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(Map.of("type", type))) + .characterEncoding(StandardCharsets.UTF_8) + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @And("The retrieved media content has type {string}") public void theRetrievedMediaContentHasType(String type) throws Exception { stepDefs.result = stepDefs.mockMvc.perform( get(mediaContentUri) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()) - .andExpect(jsonPath("$.type", is(type))); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()) + .andExpect(jsonPath("$.type", is(type))); } @When("I delete the media content with url {string}") public void iDeleteTheMediaContent(String url) throws Exception { stepDefs.result = stepDefs.mockMvc.perform( delete("/mediaContents/" + url) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @And("The media content with url {string} has been deleted") public void theMediaContentHasBeenDeleted(String url) throws Exception { stepDefs.mockMvc.perform( get("/mediaContents/" + url) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()) - .andExpect(status().isNotFound()); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()) + .andExpect(status().isNotFound()); } } diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/ManageVenueStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/ManageVenueStepDefs.java index 77eb704e..da6293c8 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/ManageVenueStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/ManageVenueStepDefs.java @@ -1,5 +1,13 @@ package cat.udl.eps.softarch.fll.steps; +import cat.udl.eps.softarch.fll.domain.Venue; +import cat.udl.eps.softarch.fll.repository.VenueRepository; +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.When; +import org.springframework.http.MediaType; +import java.nio.charset.StandardCharsets; +import java.util.NoSuchElementException; import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; @@ -13,15 +21,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import java.nio.charset.StandardCharsets; import java.util.List; -import java.util.NoSuchElementException; -import org.springframework.http.MediaType; -import cat.udl.eps.softarch.fll.domain.Venue; -import cat.udl.eps.softarch.fll.repository.VenueRepository; -import io.cucumber.java.en.And; -import io.cucumber.java.en.Given; -import io.cucumber.java.en.When; public class ManageVenueStepDefs { private final StepDefs stepDefs; @@ -39,26 +39,22 @@ public void thereIsNoVenueWithName(String name) { @Given("^There is a venue with name \"([^\"]*)\" and city \"([^\"]*)\"$") public void thereIsAVenueWithNameAndCity(String name, String city) { - Venue venue = new Venue(); - venue.setName(name); - venue.setCity(city); + Venue venue = Venue.create(name, city); venueRepository.save(venue); } @When("^I create a new venue with name \"([^\"]*)\" and city \"([^\"]*)\"$") public void iCreateANewVenueWithNameAndCity(String name, String city) throws Throwable { - Venue venue = new Venue(); - venue.setName(name); - venue.setCity(city); + Venue venue = Venue.create(name, city); stepDefs.result = stepDefs.mockMvc.perform( post("/venues") - .contentType(MediaType.APPLICATION_JSON) - .content(stepDefs.mapper.writeValueAsString(venue)) - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .contentType(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(venue)) + .characterEncoding(StandardCharsets.UTF_8) + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @When("^I retrieve the venue with name \"([^\"]*)\"$") @@ -66,27 +62,25 @@ public void iRetrieveTheVenueWithName(String name) throws Throwable { Venue venue = findVenueByName(name); stepDefs.result = stepDefs.mockMvc.perform( get("/venues/{id}", venue.getId()) - .accept(MediaType.APPLICATION_JSON) - .characterEncoding(StandardCharsets.UTF_8) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .accept(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @When("^I update the venue with name \"([^\"]*)\" to city \"([^\"]*)\"$") public void iUpdateTheVenueWithNameToCity(String name, String newCity) throws Throwable { Venue existingVenue = findVenueByName(name); - Venue venue = new Venue(); - venue.setName(name); - venue.setCity(newCity); + Venue venue = Venue.create(name, newCity); stepDefs.result = stepDefs.mockMvc.perform( put("/venues/{id}", existingVenue.getId()) - .contentType(MediaType.APPLICATION_JSON) - .content(stepDefs.mapper.writeValueAsString(venue)) - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .contentType(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(venue)) + .characterEncoding(StandardCharsets.UTF_8) + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @When("^I delete the venue with name \"([^\"]*)\"$") @@ -94,8 +88,8 @@ public void iDeleteTheVenueWithName(String name) throws Throwable { Venue venue = findVenueByName(name); stepDefs.result = stepDefs.mockMvc.perform( delete("/venues/{id}", venue.getId()) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @And("^A venue with name \"([^\"]*)\" and city \"([^\"]*)\" exists$") @@ -107,8 +101,8 @@ public void aVenueWithNameAndCityExists(String name, String city) { @And("^The response contains venue name \"([^\"]*)\" and city \"([^\"]*)\"$") public void theResponseContainsVenueNameAndCity(String name, String city) throws Throwable { stepDefs.result - .andExpect(jsonPath("$.name", is(name))) - .andExpect(jsonPath("$.city", is(city))); + .andExpect(jsonPath("$.name", is(name))) + .andExpect(jsonPath("$.city", is(city))); } @And("^The venue with name \"([^\"]*)\" has city \"([^\"]*)\"$") @@ -157,6 +151,6 @@ public void eachVenueInSearchResponseHasRequiredFields() throws Exception { private Venue findVenueByName(String name) { return venueRepository.findByName(name) - .orElseThrow(() -> new NoSuchElementException("Venue not found with name: " + name)); + .orElseThrow(() -> new NoSuchElementException("Venue not found with name: " + name)); } } diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/MatchAssignmentStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/MatchAssignmentStepDefs.java index 028061d8..7688c630 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/MatchAssignmentStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/MatchAssignmentStepDefs.java @@ -1,17 +1,5 @@ package cat.udl.eps.softarch.fll.steps; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import java.time.LocalTime; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import org.json.JSONArray; -import org.json.JSONObject; -import org.springframework.http.MediaType; import cat.udl.eps.softarch.fll.domain.Floater; import cat.udl.eps.softarch.fll.domain.Match; import cat.udl.eps.softarch.fll.domain.MatchState; @@ -26,6 +14,18 @@ import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; +import org.json.JSONArray; +import org.json.JSONObject; +import org.springframework.http.MediaType; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; public class MatchAssignmentStepDefs { private static final Long NON_EXISTENT_MATCH_ID = Long.MAX_VALUE; @@ -37,22 +37,21 @@ public class MatchAssignmentStepDefs { private final FloaterRepository floaterRepository; private final MatchResultRepository matchResultRepository; private final RoundRepository roundRepository; - + private final List batchMatches = new ArrayList<>(); private Match currentMatch; private Referee currentReferee; private Referee firstReferee; private Referee secondReferee; private Floater currentFloater; private Round currentRound; - private final List batchMatches = new ArrayList<>(); public MatchAssignmentStepDefs( - StepDefs stepDefs, - MatchRepository matchRepository, - RefereeRepository refereeRepository, - FloaterRepository floaterRepository, - MatchResultRepository matchResultRepository, - RoundRepository roundRepository) { + StepDefs stepDefs, + MatchRepository matchRepository, + RefereeRepository refereeRepository, + FloaterRepository floaterRepository, + MatchResultRepository matchResultRepository, + RoundRepository roundRepository) { this.stepDefs = stepDefs; this.matchRepository = matchRepository; this.refereeRepository = refereeRepository; @@ -89,10 +88,7 @@ public void createFinishedMatch(String startTime, String endTime) { @Given("a referee volunteer exists") public void createReferee() { - Referee referee = new Referee(); - referee.setName("Referee One"); - referee.setEmailAddress("ref" + System.nanoTime() + "@mail.com"); - referee.setPhoneNumber("123456789"); + Referee referee = Referee.create("Referee One", "ref" + System.nanoTime() + "@mail.com", "123456789"); currentReferee = refereeRepository.save(referee); if (firstReferee == null) { firstReferee = currentReferee; @@ -101,20 +97,13 @@ public void createReferee() { @Given("another referee volunteer exists") public void createAnotherReferee() { - Referee referee = new Referee(); - referee.setName("Referee Two"); - referee.setEmailAddress("ref" + System.nanoTime() + "@mail.com"); - referee.setPhoneNumber("987654321"); + Referee referee = Referee.create("Referee Two", "ref" + System.nanoTime() + "@mail.com", "987654321"); secondReferee = refereeRepository.save(referee); } @Given("a floater volunteer exists") public void createFloater() { - Floater floater = new Floater(); - floater.setName("Floater One"); - floater.setEmailAddress("floater" + System.nanoTime() + "@mail.com"); - floater.setPhoneNumber("555555555"); - floater.setStudentCode("F" + System.nanoTime()); + Floater floater = Floater.create("Floater One", "floater" + System.nanoTime() + "@mail.com", "555555555", "F" + System.nanoTime()); currentFloater = floaterRepository.save(floater); } @@ -130,10 +119,10 @@ public void createScheduledMatchAssignedToReferee(String startTime, String endTi @Given("a round with two scheduled matches exists from {string}-{string} and {string}-{string}") public void createRoundWithTwoScheduledMatches( - String firstStartTime, - String firstEndTime, - String secondStartTime, - String secondEndTime) { + String firstStartTime, + String firstEndTime, + String secondStartTime, + String secondEndTime) { currentRound = createRound(); batchMatches.clear(); batchMatches.add(createMatch(MatchState.SCHEDULED, firstStartTime, firstEndTime, null, currentRound)); @@ -142,10 +131,10 @@ public void createRoundWithTwoScheduledMatches( @Given("a round with overlapping scheduled matches exists from {string}-{string} and {string}-{string}") public void createRoundWithOverlappingScheduledMatches( - String firstStartTime, - String firstEndTime, - String secondStartTime, - String secondEndTime) { + String firstStartTime, + String firstEndTime, + String secondStartTime, + String secondEndTime) { createRoundWithTwoScheduledMatches(firstStartTime, firstEndTime, secondStartTime, secondEndTime); } @@ -177,22 +166,22 @@ public void assignRefereeIdToCurrentMatch(String refereeId) throws Exception { @When("I assign referees in batch for that round") public void assignRefereesInBatchForRound() throws Exception { assignBatch(List.of( - new BatchAssignment(batchMatches.get(0).getId(), firstReferee.getId()), - new BatchAssignment(batchMatches.get(1).getId(), secondReferee.getId()))); + new BatchAssignment(batchMatches.get(0).getId(), firstReferee.getId()), + new BatchAssignment(batchMatches.get(1).getId(), secondReferee.getId()))); } @When("I assign the same referee in batch to both matches") public void assignSameRefereeInBatchToBothMatches() throws Exception { assignBatch(List.of( - new BatchAssignment(batchMatches.get(0).getId(), firstReferee.getId()), - new BatchAssignment(batchMatches.get(1).getId(), firstReferee.getId()))); + new BatchAssignment(batchMatches.get(0).getId(), firstReferee.getId()), + new BatchAssignment(batchMatches.get(1).getId(), firstReferee.getId()))); } @When("I assign one referee and one floater in batch for that round") public void assignOneRefereeAndOneFloaterInBatchForRound() throws Exception { assignBatch(List.of( - new BatchAssignment(batchMatches.get(0).getId(), firstReferee.getId()), - new BatchAssignment(batchMatches.get(1).getId(), currentFloater.getId()))); + new BatchAssignment(batchMatches.get(0).getId(), firstReferee.getId()), + new BatchAssignment(batchMatches.get(1).getId(), currentFloater.getId()))); } @When("I assign referees in batch for round id {string}") @@ -266,11 +255,11 @@ private void assign(String matchId, String refereeId) throws Exception { request.put("matchId", matchId); request.put("refereeId", refereeId); stepDefs.result = stepDefs.mockMvc.perform( - post("/matchAssignments/assign") - .with(AuthenticationStepDefs.authenticate()) - .contentType(MediaType.APPLICATION_JSON) - .content(request.toString()) - .accept(MediaType.APPLICATION_JSON)); + post("/matchAssignments/assign") + .with(AuthenticationStepDefs.authenticate()) + .contentType(MediaType.APPLICATION_JSON) + .content(request.toString()) + .accept(MediaType.APPLICATION_JSON)); } private void assignBatch(List assignments) throws Exception { @@ -291,12 +280,13 @@ private void assignBatchForRound(String roundId, List assignmen request.put("assignments", payloadAssignments); stepDefs.result = stepDefs.mockMvc.perform( - post("/matchAssignments/batch") - .with(AuthenticationStepDefs.authenticate()) - .contentType(MediaType.APPLICATION_JSON) - .content(request.toString()) - .accept(MediaType.APPLICATION_JSON)); + post("/matchAssignments/batch") + .with(AuthenticationStepDefs.authenticate()) + .contentType(MediaType.APPLICATION_JSON) + .content(request.toString()) + .accept(MediaType.APPLICATION_JSON)); } - private record BatchAssignment(Long matchId, Long refereeId) {} + private record BatchAssignment(Long matchId, Long refereeId) { + } } diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/MatchScoreRegistrationStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/MatchScoreRegistrationStepDefs.java index 5326dbb1..c5467e50 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/MatchScoreRegistrationStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/MatchScoreRegistrationStepDefs.java @@ -1,13 +1,5 @@ package cat.udl.eps.softarch.fll.steps; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import java.nio.charset.StandardCharsets; -import java.time.LocalDate; -import java.time.LocalTime; -import java.util.UUID; -import org.json.JSONObject; -import org.springframework.http.MediaType; import cat.udl.eps.softarch.fll.domain.Match; import cat.udl.eps.softarch.fll.domain.MatchResult; import cat.udl.eps.softarch.fll.domain.Team; @@ -17,6 +9,14 @@ import io.cucumber.java.en.And; import io.cucumber.java.en.Given; import io.cucumber.java.en.When; +import org.json.JSONObject; +import org.springframework.http.MediaType; +import java.nio.charset.StandardCharsets; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.UUID; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import io.cucumber.java.en.Then; public class MatchScoreRegistrationStepDefs { @@ -30,9 +30,9 @@ public class MatchScoreRegistrationStepDefs { private Team teamB; public MatchScoreRegistrationStepDefs(StepDefs stepDefs, - TeamRepository teamRepository, - MatchRepository matchRepository, - MatchResultRepository matchResultRepository) { + TeamRepository teamRepository, + MatchRepository matchRepository, + MatchResultRepository matchResultRepository) { this.stepDefs = stepDefs; this.teamRepository = teamRepository; this.matchRepository = matchRepository; @@ -59,10 +59,7 @@ public void thereIsAMatchWithInvalidTimeRangeReadyForScoreRegistration() { @Given("^There is already a registered score for that match$") public void thereIsAlreadyARegisteredScoreForThatMatch() { - MatchResult existingResult = new MatchResult(); - existingResult.setMatch(match); - existingResult.setTeam(teamA); - existingResult.setScore(100); + MatchResult existingResult = MatchResult.create(100, match, teamA); matchResultRepository.save(existingResult); } @@ -98,9 +95,9 @@ public void iRegisterAFinalScoreWithNullScorePayload() throws Throwable { @When("^I register a final score with invalid score format$") public void iRegisterAFinalScoreWithInvalidScoreFormat() throws Throwable { String payload = "{\"matchId\":" + match.getId() - + ",\"score\":{\"teamAId\":\"" + teamA.getId() - + "\",\"teamBId\":\"" + teamB.getId() - + "\",\"teamAScore\":\"invalid\",\"teamBScore\":95}}"; + + ",\"score\":{\"teamAId\":\"" + teamA.getId() + + "\",\"teamBId\":\"" + teamB.getId() + + "\",\"teamAScore\":\"invalid\",\"teamBScore\":95}}"; postRegisterRawPayload(payload); } @@ -112,19 +109,19 @@ public void iTryToCreateAMatchResultDirectlyWithScore(int score) throws Throwabl payload.put("match", "http://localhost/matches/" + match.getId()); stepDefs.result = stepDefs.mockMvc.perform(post("/matchResults") - .contentType(MediaType.APPLICATION_JSON) - .content(payload.toString()) - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())); + .contentType(MediaType.APPLICATION_JSON) + .content(payload.toString()) + .characterEncoding(StandardCharsets.UTF_8) + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())); } @And("^The register response contains successful flags$") public void theRegisterResponseContainsSuccessfulFlags() throws Throwable { stepDefs.result - .andExpect(jsonPath("$.matchId").value(match.getId())) - .andExpect(jsonPath("$.resultSaved").value(true)) - .andExpect(jsonPath("$.rankingUpdated").value(true)); + .andExpect(jsonPath("$.matchId").value(match.getId())) + .andExpect(jsonPath("$.resultSaved").value(true)) + .andExpect(jsonPath("$.rankingUpdated").value(true)); } @Then("^The match score error response has code \"([^\"]*)\"$") @@ -136,7 +133,7 @@ public void theMatchScoreErrorResponseHasCode(String errorCode) throws Throwable } private void postRegisterScorePayload(Long matchId, String payloadTeamAId, String payloadTeamBId, int payloadTeamAScore, int payloadTeamBScore) - throws Throwable { + throws Throwable { JSONObject scorePayload = new JSONObject(); scorePayload.put("teamAId", payloadTeamAId); scorePayload.put("teamBId", payloadTeamBId); @@ -151,11 +148,11 @@ private void postRegisterScorePayload(Long matchId, String payloadTeamAId, Strin private void postRegisterRawPayload(String payload) throws Throwable { stepDefs.result = stepDefs.mockMvc.perform(post("/matchResults/register") - .contentType(MediaType.APPLICATION_JSON) - .content(payload) - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())); + .contentType(MediaType.APPLICATION_JSON) + .content(payload) + .characterEncoding(StandardCharsets.UTF_8) + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())); } private void createDefaultTeams() { @@ -174,11 +171,7 @@ private Match createMatch(LocalTime startTime, LocalTime endTime, Team assignedT } private Team createTeam(String teamName) { - Team team = new Team(); - team.setName(teamName); - team.setCity("Igualada"); - team.setFoundationYear(2000); - team.setCategory("Junior"); + Team team = Team.create(teamName, "Igualada", 2000, "Junior"); team.setEducationalCenter("EPS"); team.setInscriptionDate(LocalDate.now()); return teamRepository.save(team); diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/ProjectRoomSteps.java b/src/test/java/cat/udl/eps/softarch/fll/steps/ProjectRoomSteps.java index 14f1bb82..67b43e10 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/ProjectRoomSteps.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/ProjectRoomSteps.java @@ -8,24 +8,22 @@ import io.cucumber.java.en.Then; import io.cucumber.java.en.When; import org.springframework.http.MediaType; -import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors; - import java.util.ArrayList; import java.util.HashMap; import java.util.Map; -import java.util.UUID; - +import java.util.Random; +import java.util.random.RandomGenerator; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; public class ProjectRoomSteps { private final StepDefs stepDefs; private final ProjectRoomRepository roomRepository; private final JudgeRepository judgeRepository; - private Map judgeIdMap = new HashMap<>(); + private final Map judgeIdMap = new HashMap<>(); public ProjectRoomSteps(StepDefs stepDefs, ProjectRoomRepository roomRepository, JudgeRepository judgeRepository) { this.stepDefs = stepDefs; @@ -43,10 +41,7 @@ public void a_project_room_exists(String roomId) { @Given("a judge {string} exists") public void a_judge_exists(String judgeAlias) { - Judge judge = new Judge(); - judge.setName("Test Judge " + judgeAlias); - judge.setEmailAddress("judge_" + UUID.randomUUID().toString().substring(0, 8) + "@test.com"); - judge.setPhoneNumber("123456789"); + Judge judge = Judge.create("Test Judge " + judgeAlias, "judge_" + Random.from(RandomGenerator.getDefault()).nextFloat() + "@test.com", "123456789"); judge = judgeRepository.save(judge); judgeIdMap.put(judgeAlias, judge.getId()); } @@ -54,10 +49,7 @@ public void a_judge_exists(String judgeAlias) { @Given("the room {string} already has a manager") public void the_room_already_has_a_manager(String roomId) { ProjectRoom room = roomRepository.findById(roomId).orElseThrow(); - Judge manager = new Judge(); - manager.setName("Manager"); - manager.setEmailAddress("manager@test.com"); - manager.setPhoneNumber("000"); + Judge manager = Judge.create("Manager", "manager@test.com", "000"); manager = judgeRepository.save(manager); room.setManagedByJudge(manager); roomRepository.save(room); @@ -67,10 +59,7 @@ public void the_room_already_has_a_manager(String roomId) { public void the_room_already_has_panelists(String roomId, int count) { ProjectRoom room = roomRepository.findById(roomId).orElseThrow(); for (int i = 0; i < count; i++) { - Judge panelist = new Judge(); - panelist.setName("Panelist " + i); - panelist.setEmailAddress("p" + UUID.randomUUID().toString().substring(0, 4) + "@test.com"); - panelist.setPhoneNumber("111"); + Judge panelist = Judge.create("Panelist " + i, "p" + Random.from(RandomGenerator.getDefault()).nextFloat() + "@test.com", "111"); panelist.setMemberOfRoom(room); judgeRepository.save(panelist); } @@ -91,14 +80,14 @@ public void i_request_to_assign_judge_to_room_with_is_manager(String judgeAlias, String judgeId = judgeIdMap.containsKey(judgeAlias) ? String.valueOf(judgeIdMap.get(judgeAlias)) : judgeAlias; String jsonPayload = String.format( - "{\"roomId\": \"%s\", \"judgeId\": \"%s\", \"isManager\": %b}", - roomId, judgeId, isManager + "{\"roomId\": \"%s\", \"judgeId\": \"%s\", \"isManager\": %b}", + roomId, judgeId, isManager ); stepDefs.result = stepDefs.mockMvc.perform(post("/project-rooms/assign-judge") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonPayload) - .with(user("admin").roles("ADMIN"))); + .contentType(MediaType.APPLICATION_JSON) + .content(jsonPayload) + .with(user("admin").roles("ADMIN"))); } @Then("the response status should be {int}") @@ -109,7 +98,7 @@ public void the_response_status_should_be(int expectedStatus) throws Throwable { @Then("the response role should be {string}") public void the_response_role_should_be(String expectedRole) throws Throwable { stepDefs.result.andExpect(jsonPath("$.role").value(expectedRole)) - .andExpect(jsonPath("$.status").value("ASSIGNED")); + .andExpect(jsonPath("$.status").value("ASSIGNED")); } @Then("the response error should be {string}") @@ -119,4 +108,4 @@ public void the_response_error_should_be(String expectedError) throws Throwable .andExpect(jsonPath("$.timestamp").exists()) .andExpect(jsonPath("$.path").value("/project-rooms/assign-judge")); } -} +} \ No newline at end of file diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/RefereeSearchStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/RefereeSearchStepDefs.java index 0ff36e93..be521450 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/RefereeSearchStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/RefereeSearchStepDefs.java @@ -1,18 +1,18 @@ package cat.udl.eps.softarch.fll.steps; -import static org.hamcrest.Matchers.hasItem; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import com.fasterxml.jackson.databind.JsonNode; -import java.util.UUID; -import org.springframework.http.MediaType; import cat.udl.eps.softarch.fll.domain.Referee; import cat.udl.eps.softarch.fll.repository.RefereeRepository; +import com.fasterxml.jackson.databind.JsonNode; import io.cucumber.java.en.And; import io.cucumber.java.en.Given; import io.cucumber.java.en.When; +import org.springframework.http.MediaType; +import java.util.UUID; +import static org.hamcrest.Matchers.hasItem; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; public class RefereeSearchStepDefs { @@ -29,16 +29,10 @@ public void refereesExistWithNames(String firstRefereeName, String secondReferee refereeRepository.deleteAll(); String suffix = UUID.randomUUID().toString().substring(0, 8); - Referee firstReferee = new Referee(); - firstReferee.setName(firstRefereeName); - firstReferee.setEmailAddress("referee.search.first." + suffix + "@example.com"); - firstReferee.setPhoneNumber("333333333"); + Referee firstReferee = Referee.create(firstRefereeName, "referee.search.first." + suffix + "@example.com", "333333333"); refereeRepository.save(firstReferee); - Referee secondReferee = new Referee(); - secondReferee.setName(secondRefereeName); - secondReferee.setEmailAddress("referee.search.second." + suffix + "@example.com"); - secondReferee.setPhoneNumber("444444444"); + Referee secondReferee = Referee.create(secondRefereeName, "referee.search.second." + suffix + "@example.com", "444444444"); refereeRepository.save(secondReferee); } @@ -47,7 +41,7 @@ public void iSearchRefereesByNameContaining(String name) throws Exception { stepDefs.result = stepDefs.mockMvc.perform(get("/referees/search/findByNameContaining") .param("name", name) .accept(MediaType.APPLICATION_JSON)) - .andDo(print()); + .andDo(print()); } @And("^the referees search response should contain (\\d+) result[s]?$") diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/RefereeStepsDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/RefereeStepsDefs.java index 0f462565..3ec5f3fb 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/RefereeStepsDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/RefereeStepsDefs.java @@ -1,13 +1,13 @@ package cat.udl.eps.softarch.fll.steps; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; import cat.udl.eps.softarch.fll.domain.CompetitionTable; import cat.udl.eps.softarch.fll.domain.Referee; import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; public class RefereeStepsDefs { @@ -17,7 +17,7 @@ public class RefereeStepsDefs { @Given("a new referee") public void a_new_referee() { - referee = new Referee(); + referee = Referee.create("Default Referee", "pep@gmail.com", "123456789"); } @When("I set the referee as an expert") diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/TeamEditionRegistrationStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/TeamEditionRegistrationStepDefs.java index 7b832151..1b62d444 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/TeamEditionRegistrationStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/TeamEditionRegistrationStepDefs.java @@ -1,21 +1,5 @@ package cat.udl.eps.softarch.fll.steps; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CyclicBarrier; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.stream.IntStream; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; -import org.springframework.transaction.annotation.Transactional; import cat.udl.eps.softarch.fll.domain.Edition; import cat.udl.eps.softarch.fll.domain.EditionState; import cat.udl.eps.softarch.fll.domain.Team; @@ -25,6 +9,22 @@ import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.transaction.annotation.Transactional; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.stream.IntStream; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; public class TeamEditionRegistrationStepDefs { @@ -36,9 +36,9 @@ public class TeamEditionRegistrationStepDefs { private List concurrentResponseCodes; public TeamEditionRegistrationStepDefs(StepDefs stepDefs, - ManageEditionStepDefs manageEditionStepDefs, - EditionRepository editionRepository, - TeamRepository teamRepository) { + ManageEditionStepDefs manageEditionStepDefs, + EditionRepository editionRepository, + TeamRepository teamRepository) { this.stepDefs = stepDefs; this.manageEditionStepDefs = manageEditionStepDefs; this.editionRepository = editionRepository; @@ -48,10 +48,7 @@ public TeamEditionRegistrationStepDefs(StepDefs stepDefs, @Given("There is a team named {string} from {string} with category {string}") public void thereIsATeam(String name, String city, String category) { if (!teamRepository.existsById(name)) { - Team team = new Team(name); - team.setCity(city); - team.setFoundationYear(2000); - team.setCategory(category); + Team team = Team.create(name, city, 2000, category); teamRepository.save(team); } } @@ -72,10 +69,7 @@ public void editionHasTeamsRegistered(int count) { IntStream.range(0, count).forEach(i -> { String teamName = "FillerTeam_" + edition.getId() + "_" + i; Team team = teamRepository.findById(teamName).orElseGet(() -> { - Team created = new Team(teamName); - created.setCity("Igualada"); - created.setFoundationYear(2000); - created.setCategory("Challenge"); + Team created = Team.create(teamName, "Igualada", 2000, "Challenge"); return teamRepository.save(created); }); edition.getTeams().add(team); @@ -95,18 +89,18 @@ public void currentEditionIsInState(String state) { public void iRegisterTeamToCurrentEdition(String teamName) throws Exception { stepDefs.result = stepDefs.mockMvc.perform( post("/editions/" + currentEditionId() + "/teams/" + teamName) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @When("I register team {string} to edition with id {long}") public void iRegisterTeamToEditionById(String teamName, Long editionId) throws Exception { stepDefs.result = stepDefs.mockMvc.perform( post("/editions/" + editionId + "/teams/" + teamName) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @When("I register teams {string} and {string} concurrently to the current edition") @@ -154,13 +148,13 @@ private Long currentEditionId() { } private int performRegistration(MockMvc mockMvc, Long editionId, String teamName, - CyclicBarrier barrier) throws Exception { + CyclicBarrier barrier) throws Exception { barrier.await(); MvcResult result = mockMvc.perform( post("/editions/" + editionId + "/teams/" + teamName) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andReturn(); + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andReturn(); return result.getResponse().getStatus(); } } diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/TeamMemberStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/TeamMemberStepDefs.java index 6934e2b5..9ba6e1af 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/TeamMemberStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/TeamMemberStepDefs.java @@ -1,5 +1,18 @@ package cat.udl.eps.softarch.fll.steps; +import cat.udl.eps.softarch.fll.domain.Team; +import cat.udl.eps.softarch.fll.repository.TeamMemberRepository; +import cat.udl.eps.softarch.fll.repository.TeamRepository; +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import org.json.JSONObject; +import org.springframework.http.MediaType; +import org.springframework.web.util.UriUtils; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.time.LocalDate; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.is; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; @@ -8,19 +21,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.time.LocalDate; -import org.json.JSONObject; -import org.springframework.http.MediaType; -import org.springframework.web.util.UriUtils; -import cat.udl.eps.softarch.fll.domain.Team; -import cat.udl.eps.softarch.fll.repository.TeamMemberRepository; -import cat.udl.eps.softarch.fll.repository.TeamRepository; -import io.cucumber.java.en.And; -import io.cucumber.java.en.Given; -import io.cucumber.java.en.Then; -import io.cucumber.java.en.When; public class TeamMemberStepDefs { @@ -51,10 +51,7 @@ public void aTeamWithNameExistsForTeamMemberManagement(String teamName) { if (teamRepository.existsById(teamName)) { return; } - Team team = new Team(teamName); - team.setCity("Igualada"); - team.setFoundationYear(2005); - team.setCategory("Challenge"); + Team team = Team.create(teamName, "Igualada", 2005, "Challenge"); teamRepository.save(team); } @@ -64,12 +61,12 @@ public void iCreateATeamMemberForTeam(String name, String birthDate, String role stepDefs.result = stepDefs.mockMvc.perform( post("/teamMembers") - .contentType(MediaType.APPLICATION_JSON) - .content(payload.toString()) - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .contentType(MediaType.APPLICATION_JSON) + .content(payload.toString()) + .characterEncoding(StandardCharsets.UTF_8) + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); captureLatestTeamMemberIfCreated(); } @@ -77,17 +74,17 @@ public void iCreateATeamMemberForTeam(String name, String birthDate, String role @When("I try to create a team member missing {string} for team {string}") public void iTryToCreateATeamMemberMissingField(String field, String teamName) throws Exception { JSONObject payload = - buildTeamMemberPayload("Valid Name", LocalDate.of(2010, 1, 1).toString(), "Builder", teamName); + buildTeamMemberPayload("Valid Name", LocalDate.of(2010, 1, 1).toString(), "Builder", teamName); payload.remove(field); stepDefs.result = stepDefs.mockMvc.perform( post("/teamMembers") - .contentType(MediaType.APPLICATION_JSON) - .content(payload.toString()) - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .contentType(MediaType.APPLICATION_JSON) + .content(payload.toString()) + .characterEncoding(StandardCharsets.UTF_8) + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @When("I retrieve the created team member by id") @@ -95,20 +92,20 @@ public void iRetrieveTheCreatedTeamMemberById() throws Exception { assertLatestTeamMemberIdPresent(); stepDefs.result = stepDefs.mockMvc.perform( get("/teamMembers/{id}", latestTeamMemberId) - .accept(MediaType.APPLICATION_JSON) - .characterEncoding(StandardCharsets.UTF_8) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .accept(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @When("I list all team members") public void iListAllTeamMembers() throws Exception { stepDefs.result = stepDefs.mockMvc.perform( get("/teamMembers") - .accept(MediaType.APPLICATION_JSON) - .characterEncoding(StandardCharsets.UTF_8) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .accept(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @When("I delete the created team member") @@ -116,8 +113,8 @@ public void iDeleteTheCreatedTeamMember() throws Exception { assertLatestTeamMemberIdPresent(); stepDefs.result = stepDefs.mockMvc.perform( delete("/teamMembers/{id}", latestTeamMemberId) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()); + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } @When("I retrieve the deleted team member by id") @@ -130,13 +127,13 @@ public void theCreatedTeamMemberHasNameAndRole(String expectedName, String expec assertLatestTeamMemberUriPresent(); stepDefs.mockMvc.perform( get(pathFromAbsoluteUri(latestTeamMemberUri)) - .accept(MediaType.APPLICATION_JSON) - .characterEncoding(StandardCharsets.UTF_8) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.name", is(expectedName))) - .andExpect(jsonPath("$.role", is(expectedRole))); + .accept(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.name", is(expectedName))) + .andExpect(jsonPath("$.role", is(expectedRole))); } @Then("The created team member is linked to team {string}") @@ -144,19 +141,19 @@ public void theCreatedTeamMemberIsLinkedToTeam(String expectedTeamName) throws E assertLatestTeamMemberUriPresent(); stepDefs.mockMvc.perform( get(pathFromAbsoluteUri(latestTeamMemberUri) + "/team") - .accept(MediaType.APPLICATION_JSON) - .characterEncoding(StandardCharsets.UTF_8) - .with(AuthenticationStepDefs.authenticate())) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id", is(expectedTeamName))); + .accept(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(expectedTeamName))); } @Then("The response contains team member name {string} and role {string}") public void theResponseContainsTeamMemberNameAndRole(String expectedName, String expectedRole) throws Exception { stepDefs.result - .andExpect(jsonPath("$.name", is(expectedName))) - .andExpect(jsonPath("$.role", is(expectedRole))); + .andExpect(jsonPath("$.name", is(expectedName))) + .andExpect(jsonPath("$.role", is(expectedRole))); } @And("The team member list contains name {string}") @@ -194,7 +191,7 @@ private void captureLatestTeamMemberIfCreated() throws Exception { latestTeamMemberId = Long.valueOf(idToken); } catch (NumberFormatException e) { throw new IllegalStateException( - "Could not parse team member ID from Location header: " + latestTeamMemberUri, e); + "Could not parse team member ID from Location header: " + latestTeamMemberUri, e); } } diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/TeamSteps.java b/src/test/java/cat/udl/eps/softarch/fll/steps/TeamSteps.java index c14c607a..c56c7978 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/TeamSteps.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/TeamSteps.java @@ -1,12 +1,5 @@ package cat.udl.eps.softarch.fll.steps; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import java.util.List; -import java.util.stream.IntStream; -import org.springframework.transaction.annotation.Transactional; import cat.udl.eps.softarch.fll.domain.Team; import cat.udl.eps.softarch.fll.domain.TeamMember; import cat.udl.eps.softarch.fll.repository.TeamMemberRepository; @@ -14,6 +7,14 @@ import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; +import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.IntStream; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; public class TeamSteps { @@ -40,19 +41,12 @@ public void clearDB() { @Given("I create a team named {string} from {string}") public void iCreateATeam(String name, String city) { - currentTeam = new Team(name); - currentTeam.setCity(city); - currentTeam.setFoundationYear(2000); - currentTeam.setCategory("Challenge"); + currentTeam = Team.create(name, city, 2000, "Challenge"); } @Given("I add a member named {string} with role {string}") public void iAddAMember(String name, String role) { - TeamMember member = new TeamMember(); - member.setName(name); - member.setRole(role); - member.setBirthDate(java.time.LocalDate.of(2010, 1, 1)); - currentTeam.addMember(member); + TeamMember.create(name, role, LocalDate.of(2010, 1, 1), currentTeam); } @When("I save the team") @@ -75,10 +69,7 @@ public void theTeamShouldHaveMembers(int count) { @When("I try to create an invalid team named {string} from {string}") public void tryCreateInvalid(String name, String city) { try { - Team team = new Team(name); - team.setCity(city); - team.setFoundationYear(2000); - team.setCategory("Challenge"); + Team team = Team.create(name, city, 2000, "Challenge"); teamRepository.save(team); } catch (Exception e) { lastException = e; @@ -92,17 +83,10 @@ public void checkError() { @Given("I have a team named {string} with {int} members") public void createTeamWithManyMembers(String name, int count) { - currentTeam = new Team(name); - currentTeam.setCity("Igualada"); - currentTeam.setFoundationYear(2000); - currentTeam.setCategory("Challenge"); + currentTeam = Team.create(name, "Igualada", 2000, "Challenge"); IntStream.range(0, count).forEach(i -> { - TeamMember m = new TeamMember(); - m.setName("Member " + i); - m.setRole("Student"); - m.setBirthDate(java.time.LocalDate.of(2010, 1, 1)); - currentTeam.addMember(m); + TeamMember.create("Member " + i, "Student", LocalDate.of(2010, 1, 1), currentTeam); }); teamRepository.save(currentTeam); } @@ -112,12 +96,7 @@ public void createTeamWithManyMembers(String name, int count) { public void tryAddExtraMember() { try { Team loadedTeam = teamRepository.findById(currentTeam.getId()).orElseThrow(); - TeamMember extra = new TeamMember(); - extra.setName("Extra Member"); - extra.setRole("Substitute"); - extra.setBirthDate(java.time.LocalDate.of(2012, 5, 5)); - - loadedTeam.addMember(extra); + TeamMember.create("Extra Member", "Substitute", LocalDate.of(2012, 5, 5), loadedTeam); teamRepository.save(loadedTeam); } catch (Exception e) { lastException = e; @@ -137,7 +116,7 @@ public void verifyErrorMessage(String expectedMessage) { current = current.getCause(); } assertTrue(found, "Error message '" + expectedMessage + "' not found in exception chain. Got: " - + lastException.getMessage()); + + lastException.getMessage()); } @Given("I have a team {string} with a member {string}") diff --git a/src/test/java/cat/udl/eps/softarch/fll/steps/VolunteerStepDefs.java b/src/test/java/cat/udl/eps/softarch/fll/steps/VolunteerStepDefs.java index 01a586da..22856433 100644 --- a/src/test/java/cat/udl/eps/softarch/fll/steps/VolunteerStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/fll/steps/VolunteerStepDefs.java @@ -1,11 +1,6 @@ package cat.udl.eps.softarch.fll.steps; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import java.util.List; -import java.util.Optional; -import org.springframework.transaction.annotation.Transactional; +import cat.udl.eps.softarch.fll.domain.DomainValidationException; import cat.udl.eps.softarch.fll.domain.Floater; import cat.udl.eps.softarch.fll.domain.Team; import cat.udl.eps.softarch.fll.repository.FloaterRepository; @@ -14,6 +9,12 @@ import io.cucumber.java.en.Then; import io.cucumber.java.en.When; import jakarta.validation.ConstraintViolationException; +import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.Optional; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; public class VolunteerStepDefs { @@ -43,11 +44,7 @@ public void clearVolunteerSystem() { @When("I create a floater with name {string}, email {string}, phone {string} and student code {string}") public void createFloater(String name, String email, String phone, String studentCode) { - currentFloater = new Floater(); - currentFloater.setName(name); - currentFloater.setEmailAddress(email); - currentFloater.setPhoneNumber(phone); - currentFloater.setStudentCode(studentCode); + currentFloater = Floater.create(name, email, phone, studentCode); } @When("I save the floater") @@ -85,11 +82,7 @@ public void tryAssignFloaterToTeam(String studentCode, String teamName) { @When("I try to create a floater with name {string} and email {string} and phone {string} and student code {string}") public void tryCreateInvalidFloater(String name, String email, String phone, String studentCode) { try { - Floater floater = new Floater(); - floater.setName(name); - floater.setEmailAddress(email); - floater.setPhoneNumber(phone); - floater.setStudentCode(studentCode); + Floater floater = Floater.create(name, email, phone, studentCode); floaterRepository.save(floater); } catch (Exception e) { lastException = e; @@ -100,14 +93,15 @@ public void tryCreateInvalidFloater(String name, String email, String phone, Str public void floaterCreationShouldFail() { assertNotNull(lastException); assertTrue(isValidationOrConstraintException(lastException), - "Expected a validation or constraint exception but got: " + lastException.getClass().getName()); + "Expected a validation or constraint exception but got: " + lastException.getClass().getName()); } private boolean isValidationOrConstraintException(Throwable ex) { Throwable current = ex; while (current != null) { if (current instanceof ConstraintViolationException - || current instanceof org.springframework.dao.DataIntegrityViolationException) { + || current instanceof org.springframework.dao.DataIntegrityViolationException + || current instanceof DomainValidationException) { return true; } current = current.getCause(); @@ -119,8 +113,8 @@ private boolean isValidationOrConstraintException(Throwable ex) { public void verifyErrorMessage(String expectedMessage) { assertNotNull(lastException, "No exception was captured"); assertTrue(findMessageInExceptionChain(lastException, expectedMessage), - "Error message '" + expectedMessage + "' not found in exception chain. Got: " - + lastException.getMessage()); + "Error message '" + expectedMessage + "' not found in exception chain. Got: " + + lastException.getMessage()); } private boolean findMessageInExceptionChain(Throwable ex, String expectedMessage) { @@ -178,10 +172,7 @@ public void verifySearchResultCount(int count) { @Given("a team named {string} from city {string} exists for floater assignment") public void createTeamForFloaterAssignment(String name, String city) { - currentTeam = new Team(name); - currentTeam.setCity(city); - currentTeam.setFoundationYear(2020); - currentTeam.setCategory("Challenge"); + currentTeam = Team.create(name, city, 2020, "Challenge"); currentTeam = teamRepository.save(currentTeam); }