diff --git a/pom.xml b/pom.xml index f07d625..e192968 100644 --- a/pom.xml +++ b/pom.xml @@ -110,6 +110,22 @@ spring-boot-starter-test test + + org.mockito + mockito-core + 5.12.0 + + + com.github.mvysny.kaributesting + karibu-testing-v23 + 2.1.8 + + + com.github.mvysny.kaributesting + karibu-testing-v10-spring + 2.1.8 + test + org.hibernate.validator hibernate-validator @@ -200,6 +216,11 @@ commons-lang3 3.14.0 + + org.apache.maven.plugins + maven-surefire-plugin + 3.3.1 + @@ -243,6 +264,11 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 3.3.1 + diff --git a/src/main/java/com/primefactorsolutions/model/Assessment.java b/src/main/java/com/primefactorsolutions/model/Assessment.java index ff495b6..29d763f 100644 --- a/src/main/java/com/primefactorsolutions/model/Assessment.java +++ b/src/main/java/com/primefactorsolutions/model/Assessment.java @@ -27,7 +27,8 @@ public class Assessment extends BaseEntity { @ManyToOne private Candidate candidate; - @OneToMany(fetch = FetchType.EAGER, mappedBy = "assessment", cascade = {CascadeType.ALL}) + @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}) + @JoinColumn(name="ASSESSMENT_ID") private List assessmentEvents = new ArrayList<>(); public Submission getCurrentSubmission() { diff --git a/src/main/java/com/primefactorsolutions/model/AssessmentEvent.java b/src/main/java/com/primefactorsolutions/model/AssessmentEvent.java index 8da7084..aa07c7a 100644 --- a/src/main/java/com/primefactorsolutions/model/AssessmentEvent.java +++ b/src/main/java/com/primefactorsolutions/model/AssessmentEvent.java @@ -1,7 +1,6 @@ package com.primefactorsolutions.model; import jakarta.persistence.Entity; -import jakarta.persistence.ManyToOne; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; @@ -17,7 +16,4 @@ import java.time.Instant; public class AssessmentEvent extends BaseEntity { private Instant timestamp; private AssessmentStatus status; - - @ManyToOne - private Assessment assessment; } diff --git a/src/main/java/com/primefactorsolutions/service/AssessmentService.java b/src/main/java/com/primefactorsolutions/service/AssessmentService.java index a5bfa87..ef865ab 100644 --- a/src/main/java/com/primefactorsolutions/service/AssessmentService.java +++ b/src/main/java/com/primefactorsolutions/service/AssessmentService.java @@ -71,7 +71,7 @@ public class AssessmentService { return assessment; } - assessment.getAssessmentEvents().add(new AssessmentEvent(Instant.now(), AssessmentStatus.STARTED, assessment)); + assessment.getAssessmentEvents().add(new AssessmentEvent(Instant.now(), AssessmentStatus.STARTED)); return assessmentRepository.save(assessment); } @@ -169,8 +169,7 @@ public class AssessmentService { return assessment; } - assessment.getAssessmentEvents().add(new AssessmentEvent(Instant.now(), AssessmentStatus.COMPLETED, - assessment)); + assessment.getAssessmentEvents().add(new AssessmentEvent(Instant.now(), AssessmentStatus.COMPLETED)); Assessment saved = assessmentRepository.save(assessment); return saved; diff --git a/src/test/java/com/primefactorsolutions/service/AssessmentServiceTests.java b/src/test/java/com/primefactorsolutions/service/AssessmentServiceTests.java new file mode 100644 index 0000000..6199445 --- /dev/null +++ b/src/test/java/com/primefactorsolutions/service/AssessmentServiceTests.java @@ -0,0 +1,50 @@ +package com.primefactorsolutions.service; + +import com.primefactorsolutions.model.Assessment; +import com.primefactorsolutions.model.AssessmentEvent; +import com.primefactorsolutions.model.AssessmentStatus; +import com.primefactorsolutions.repositories.AssessmentRepository; +import jakarta.persistence.EntityManager; +import org.assertj.core.api.Assertions; +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 org.springframework.mail.javamail.JavaMailSender; + +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class AssessmentServiceTests { + + @Mock + private AssessmentRepository assessmentRepository; + @Mock + private EntityManager entityManager; + @Mock + private JavaMailSender emailSender; + @InjectMocks + private AssessmentService assessmentService; + + @Test + public void testAlreadyStartedAssessment() { + final var aid = UUID.randomUUID(); + final var assessment = new Assessment(); + assessment.setId(aid); + assessment.setAssessmentEvents(List.of(new AssessmentEvent(Instant.now(), AssessmentStatus.STARTED))); + + when(assessmentRepository.findById(eq(aid))) + .thenReturn(Optional.of(assessment)); + + final var started = assessmentService.startAssessment(aid); + + Assertions.assertThat(assessment).isEqualTo(started); + } +} diff --git a/src/test/java/com/primefactorsolutions/service/CompilerServiceTests.java b/src/test/java/com/primefactorsolutions/service/CompilerServiceTests.java new file mode 100644 index 0000000..2630503 --- /dev/null +++ b/src/test/java/com/primefactorsolutions/service/CompilerServiceTests.java @@ -0,0 +1,22 @@ +package com.primefactorsolutions.service; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Optional; + +@ExtendWith(MockitoExtension.class) +public class CompilerServiceTests { + @InjectMocks + private CompilerService compilerService; + + @Test + public void testDoCompile() { + final var result = compilerService.doCompile("package com.primefactorsolutions; import java.util.*; public class TestClass { public static Map run() { return Map.of(\"test\", true); } }"); + + Assertions.assertThat(result).isEqualTo(Optional.of(String.format("%-50s ... %4s", "test", "OK"))); + } +} diff --git a/src/test/java/com/primefactorsolutions/views/AbstractAppTests.java b/src/test/java/com/primefactorsolutions/views/AbstractAppTests.java new file mode 100644 index 0000000..f05c2ef --- /dev/null +++ b/src/test/java/com/primefactorsolutions/views/AbstractAppTests.java @@ -0,0 +1,73 @@ +package com.primefactorsolutions.views; + +import com.github.mvysny.fakeservlet.FakeRequest; +import com.github.mvysny.kaributesting.v10.MockVaadin; +import com.github.mvysny.kaributesting.v10.spring.MockSpringServlet; +import com.vaadin.flow.component.UI; +import com.vaadin.flow.server.VaadinServletRequest; +import com.vaadin.flow.spring.SpringServlet; + +import kotlin.jvm.functions.Function0; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; + +import com.github.mvysny.kaributesting.v10.MockVaadin; +import com.github.mvysny.kaributesting.v10.Routes; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +@SpringBootTest +public class AbstractAppTests { + private static final Routes routes = new Routes().autoDiscoverViews("com.primefactorsolutions"); + + @Autowired + protected ApplicationContext ctx; + + protected void login(String user, String pass, final List roles) { + final List authorities = + roles.stream().map(it -> new SimpleGrantedAuthority("ROLE_" + it)).collect(Collectors.toList()); + UsernamePasswordAuthenticationToken authReq + = new UsernamePasswordAuthenticationToken(new User(user, pass, authorities), pass, authorities); + SecurityContext sc = SecurityContextHolder.getContext(); + sc.setAuthentication(authReq); + + // however, you also need to make sure that ViewAccessChecker works properly; + // that requires a correct MockRequest.userPrincipal and MockRequest.isUserInRole() + final FakeRequest request = (FakeRequest) VaadinServletRequest.getCurrent().getRequest(); + request.setUserPrincipalInt(authReq); + request.setUserInRole((principal, role) -> roles.contains(role)); + } + + protected void logout() { + if (VaadinServletRequest.getCurrent() != null) { + final FakeRequest request = (FakeRequest) VaadinServletRequest.getCurrent().getRequest(); + request.setUserPrincipalInt(null); + request.setUserInRole((principal, role) -> false); + } + } + + @BeforeEach + public void setup() { + final Function0 uiFactory = UI::new; + final SpringServlet servlet = new MockSpringServlet(routes, ctx, uiFactory); + MockVaadin.setup(uiFactory, servlet); + } + + @AfterEach + public void tearDown() { + logout(); + MockVaadin.tearDown(); + } +} diff --git a/src/test/java/com/primefactorsolutions/views/CandidateViewTests.java b/src/test/java/com/primefactorsolutions/views/CandidateViewTests.java new file mode 100644 index 0000000..25bdfbc --- /dev/null +++ b/src/test/java/com/primefactorsolutions/views/CandidateViewTests.java @@ -0,0 +1,25 @@ +package com.primefactorsolutions.views; + +import com.vaadin.flow.component.UI; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.textfield.EmailField; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static com.github.mvysny.kaributesting.v10.LocatorJ.*; + +public class CandidateViewTests extends AbstractAppTests { + @BeforeEach + public void login() { + login("user", "user", List.of("user")); + } + + @Test + public void sayHelloWithMockBean() { + UI.getCurrent().navigate(CandidateView.class, "new"); + _setValue(_get(EmailField.class, spec -> spec.withLabel("Email")), "foo@test.com"); + _click(_get(Button.class, spec -> spec.withText("Save"))); + } +}