Skip to content

Commit

Permalink
Add tests with Spybeans for interceptors
Browse files Browse the repository at this point in the history
  • Loading branch information
spokenbird authored and bseeger committed Sep 25, 2023
1 parent e232343 commit b379213
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package formflow.library.exceptions;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public class LandmarkNotSetException extends RuntimeException {
public LandmarkNotSetException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import formflow.library.config.FlowConfiguration;
import formflow.library.config.ScreenNavigationConfiguration;
import formflow.library.exceptions.LandmarkNotSetException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
Expand All @@ -11,14 +12,15 @@
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.servlet.HandlerInterceptor;

@Component
@Slf4j
@ConditionalOnProperty(name = "form-flow.session-continuity-interceptor.enabled", havingValue = "true")
public class DataRequiredInterceptor implements HandlerInterceptor {
public class DataRequiredInterceptor implements HandlerInterceptor, Ordered {

public static final String FLOW_PATH_FORMAT = "/flow/{flow}/{screen}";
public static final String NAVIGATION_FLOW_PATH_FORMAT = "/flow/{flow}/{screen}/navigation";
Expand Down Expand Up @@ -50,20 +52,20 @@ public boolean preHandle(HttpServletRequest request, @NotNull HttpServletRespons
boolean landmarkNotImplemented = flowConfiguration.getLandmarks() == null;

if (landmarkNotImplemented) {
throw new RuntimeException("You have enabled session continuity interception but have not created a landmark section in your applications flow configuration file.");
throw new LandmarkNotSetException("You have enabled session continuity interception but have not created a landmark section in your applications flow configuration file.");
}

boolean firstScreenNotSet = flowConfiguration.getLandmarks().getFirstScreen() == null;

if (firstScreenNotSet) {
throw new RuntimeException("Please make sure to set a firstScreen under your flow configuration files landmark section.");
throw new LandmarkNotSetException("Please make sure to set a firstScreen under your flow configuration files landmark section.");
}

String firstScreen = flowConfiguration.getLandmarks().getFirstScreen();
boolean firstScreenExists = flowConfiguration.getFlow().containsKey(firstScreen);

if (!firstScreenExists) {
throw new RuntimeException(String.format("Please make sure that you have correctly set the firstScreen under your flow configuration files landmark section. Your flow configuration file does not contain a screen with the name %s.", firstScreen));
throw new LandmarkNotSetException(String.format("Please make sure that you have correctly set the firstScreen under your flow configuration files landmark section. Your flow configuration file does not contain a screen with the name %s.", firstScreen));
}

boolean onFirstScreen = screen.equals(firstScreen);
Expand All @@ -88,4 +90,10 @@ public boolean preHandle(HttpServletRequest request, @NotNull HttpServletRespons
return true;
}
}

@Override
public int getOrder() {
// Max value ensures that this interceptor is executed last.
return Integer.MAX_VALUE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
import org.junit.jupiter.api.Test;
import org.openqa.selenium.Cookie;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;

@SpringBootTest(properties = {"form-flow.path=flows-config/test-landmark-flow.yaml"}, webEnvironment = RANDOM_PORT)
@TestPropertySource(properties = {"form-flow.session-continuity-interceptor.enabled=true"})
public class DataInterceptorJourneyTest extends AbstractBasePageTest {
@Test
void interceptorShouldRedirectToLandingPageIfSessionIsNull() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package formflow.library.interceptors;


import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.inOrder;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import formflow.library.config.FlowConfiguration;
import formflow.library.config.LandmarkConfiguration;
import formflow.library.config.NextScreen;
import formflow.library.config.ScreenNavigationConfiguration;
import formflow.library.exceptions.LandmarkNotSetException;
import formflow.library.utilities.AbstractMockMvcTest;
import java.util.HashMap;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.mockito.InOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

@SpringBootTest(properties = {"form-flow.path=flows-config/test-landmark-flow.yaml"})
@TestPropertySource(properties = {"form-flow.session-continuity-interceptor.enabled=true"})
@Import(SpyInterceptorConfig.class)
class InterceptorOrderMockMvcTest extends AbstractMockMvcTest {

@Autowired
private LocaleChangeInterceptor localeChangeInterceptor;

@Autowired
private DataRequiredInterceptor dataRequiredInterceptor;

@Test
void shouldRunTheDataRequiredInterceptorLast() throws Exception {
mockMvc.perform(get("/flow/testLandmarkFlow/first?lang=es"))
.andExpect(status().isOk());

InOrder inOrder = inOrder(localeChangeInterceptor, dataRequiredInterceptor);
inOrder.verify(localeChangeInterceptor).preHandle(any(), any(), any());
inOrder.verify(dataRequiredInterceptor).preHandle(any(), any(), any());
}

@Test
void shouldErrorIfLandmarkIsNotSet() throws Exception {
FlowConfiguration flowConfiguration = new FlowConfiguration();
flowConfiguration.setName("testLandmarkFlow");
dataRequiredInterceptor.flowConfigurations = List.of(flowConfiguration);
mockMvc.perform(MockMvcRequestBuilders.get("/flow/testLandmarkFlow/first"))
.andExpect(status().is5xxServerError())
.andExpect(result -> {
Exception resolvedException = result.getResolvedException();
assertTrue(resolvedException instanceof LandmarkNotSetException, "Expected RuntimeException to be thrown");
assertEquals("You have enabled session continuity interception but have not created a landmark section in your applications flow configuration file.", resolvedException.getMessage());
});
}

@Test
void shouldErrorIfFirstScreenIsNotSet() throws Exception {
FlowConfiguration flowConfiguration = new FlowConfiguration();
flowConfiguration.setName("testLandmarkFlow");
LandmarkConfiguration landmarkConfiguration = new LandmarkConfiguration();
landmarkConfiguration.setFirstScreen(null);
flowConfiguration.setLandmarks(landmarkConfiguration);
dataRequiredInterceptor.flowConfigurations = List.of(flowConfiguration);
mockMvc.perform(MockMvcRequestBuilders.get("/flow/testLandmarkFlow/first"))
.andExpect(status().is5xxServerError())
.andExpect(result -> {
Exception resolvedException = result.getResolvedException();
assertTrue(resolvedException instanceof LandmarkNotSetException, "Expected RuntimeException to be thrown");
assertEquals("Please make sure to set a firstScreen under your flow configuration files landmark section.", resolvedException.getMessage());
});
}

@Test
void shouldErrorIfFirstScreenDoesNotExistWithinFlowConfiguration() throws Exception {
FlowConfiguration flowConfiguration = new FlowConfiguration();
ScreenNavigationConfiguration screenNavigationConfiguration = new ScreenNavigationConfiguration();
NextScreen nextScreen = new NextScreen();
nextScreen.setName("first");
screenNavigationConfiguration.setNextScreens(List.of(nextScreen));
HashMap<String, ScreenNavigationConfiguration> screenNavigationConfigurations = new HashMap<>();
screenNavigationConfigurations.put("first", screenNavigationConfiguration);
flowConfiguration.setFlow(screenNavigationConfigurations);
flowConfiguration.setName("testLandmarkFlow");
LandmarkConfiguration landmarkConfiguration = new LandmarkConfiguration();
landmarkConfiguration.setFirstScreen("nonExistentScreen");
flowConfiguration.setLandmarks(landmarkConfiguration);
dataRequiredInterceptor.flowConfigurations = List.of(flowConfiguration);

mockMvc.perform(MockMvcRequestBuilders.get("/flow/testLandmarkFlow/first"))
.andExpect(status().is5xxServerError())
.andExpect(result -> {
Exception resolvedException = result.getResolvedException();
assertTrue(resolvedException instanceof LandmarkNotSetException, "Expected RuntimeException to be thrown");
assertEquals("Please make sure that you have correctly set the firstScreen under your flow configuration files landmark section. Your flow configuration file does not contain a screen with the name nonExistentScreen.", resolvedException.getMessage());
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package formflow.library.interceptors;

import formflow.library.config.FlowConfiguration;
import java.util.List;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

@TestConfiguration
public class SpyInterceptorConfig implements WebMvcConfigurer {

@Autowired
private List<FlowConfiguration> flowConfigurations;

@Bean
@Primary
public LocaleChangeInterceptor localeChangeInterceptor() {
return Mockito.spy(new LocaleChangeInterceptor());
}

@Bean
@Primary // Ensure this bean takes precedence over the real one
public DataRequiredInterceptor dataRequiredInterceptor() {
return Mockito.spy(new DataRequiredInterceptor(flowConfigurations));
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
registry.addInterceptor(dataRequiredInterceptor());
}
}
2 changes: 0 additions & 2 deletions src/test/resources/application-test.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
form-flow:
path: 'test-flow.yaml'
inputs: 'formflow.library.inputs.'
session-continuity-interceptor:
enabled: true
uploads:
accepted-file-types: '.jpeg, .fake, .heic, .tif, .tiff, .pdf'
max-files: '5'
Expand Down

0 comments on commit b379213

Please sign in to comment.