package org.molgenis.ui.controller;
import org.molgenis.auth.User;
import org.molgenis.auth.UserFactory;
import org.molgenis.data.DataService;
import org.molgenis.data.settings.AppSettings;
import org.molgenis.framework.ui.MolgenisPluginRegistry;
import org.molgenis.security.captcha.CaptchaException;
import org.molgenis.security.captcha.CaptchaService;
import org.molgenis.security.user.UserService;
import org.molgenis.test.data.AbstractMolgenisSpringTest;
import org.molgenis.ui.controller.FeedbackControllerTest.Config;
import org.molgenis.util.GsonConfig;
import org.molgenis.util.GsonHttpMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.MailSendException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@WebAppConfiguration
@ContextConfiguration(classes = { Config.class, GsonConfig.class })
public class FeedbackControllerTest extends AbstractMolgenisSpringTest
{
@Autowired
private FeedbackController feedbackController;
@Autowired
private UserService userService;
@Autowired
private JavaMailSender javaMailSender;
@Autowired
private CaptchaService captchaService;
@Autowired
private GsonHttpMessageConverter gsonHttpMessageConverter;
@Autowired
private AppSettings appSettings;
@Autowired
private UserFactory userFactory;
private MockMvc mockMvcFeedback;
@BeforeMethod
public void beforeMethod() throws CaptchaException
{
reset(javaMailSender, appSettings, userService);
when(appSettings.getTitle()).thenReturn("app123");
mockMvcFeedback = MockMvcBuilders.standaloneSetup(feedbackController)
.setMessageConverters(gsonHttpMessageConverter).build();
Authentication authentication = new TestingAuthenticationToken("userName", null);
authentication.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(authentication);
reset(captchaService);
when(captchaService.validateCaptcha("validCaptcha")).thenReturn(true);
}
@Test
public void initFeedbackAnonymous() throws Exception
{
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("anonymous", null));
List<String> adminEmails = Collections.singletonList("molgenis@molgenis.org");
when(userService.getSuEmailAddresses()).thenReturn(adminEmails);
verify(userService, never()).getUser("anonymous");
mockMvcFeedback.perform(get(FeedbackController.URI)).andExpect(status().isOk())
.andExpect(view().name("view-feedback")).andExpect(model().attribute("adminEmails", adminEmails))
.andExpect(model().attributeDoesNotExist("userName"))
.andExpect(model().attributeDoesNotExist("userEmail"));
}
@Test
public void initFeedbackLoggedIn() throws Exception
{
List<String> adminEmails = Collections.singletonList("molgenis@molgenis.org");
User user = userFactory.create();
user.setFirstName("First");
user.setLastName("Last");
user.setEmail("user@blah.org");
when(userService.getUser("userName")).thenReturn(user);
when(userService.getSuEmailAddresses()).thenReturn(adminEmails);
mockMvcFeedback.perform(get(FeedbackController.URI)).andExpect(status().isOk())
.andExpect(view().name("view-feedback")).andExpect(model().attribute("adminEmails", adminEmails))
.andExpect(model().attribute("userName", "First Last"))
.andExpect(model().attribute("userEmail", "user@blah.org"));
}
@Test
public void initFeedbackLoggedInDetailsUnknown() throws Exception
{
User user = userFactory.create();
when(userService.getUser("userName")).thenReturn(user);
List<String> adminEmails = Collections.singletonList("molgenis@molgenis.org");
when(userService.getSuEmailAddresses()).thenReturn(adminEmails);
mockMvcFeedback.perform(get(FeedbackController.URI)).andExpect(status().isOk())
.andExpect(view().name("view-feedback")).andExpect(model().attribute("adminEmails", adminEmails))
.andExpect(model().attributeDoesNotExist("userName"))
.andExpect(model().attributeDoesNotExist("userEmail"));
}
@Test
public void submit() throws Exception
{
MimeMessage message = mock(MimeMessage.class);
when(javaMailSender.createMimeMessage()).thenReturn(message);
List<String> adminEmails = Collections.singletonList("molgenis@molgenis.org");
when(userService.getSuEmailAddresses()).thenReturn(adminEmails);
mockMvcFeedback.perform(MockMvcRequestBuilders.post(FeedbackController.URI).param("name", "First Last")
.param("subject", "Feedback form").param("email", "user@domain.com")
.param("feedback", "Feedback.\nLine two.").param("captcha", "validCaptcha")).andExpect(status().isOk())
.andExpect(view().name("view-feedback"))
.andExpect(model().attribute("feedbackForm", hasProperty("submitted", equalTo(true))));
verify(message, times(1)).setRecipients(RecipientType.TO,
new InternetAddress[] { new InternetAddress("molgenis@molgenis.org") });
verify(message, times(1)).setRecipient(RecipientType.CC, new InternetAddress("user@domain.com"));
verify(message, times(1)).setReplyTo(new InternetAddress[] { new InternetAddress("user@domain.com") });
verify(message, times(1)).setSubject("[feedback-app123] Feedback form");
verify(message, times(1)).setText("Feedback from First Last (user@domain.com):\n\n" + "Feedback.\nLine two.");
verify(javaMailSender, times(1)).send(message);
verify(captchaService, times(1)).validateCaptcha("validCaptcha");
}
@Test
public void submitFeedbackNotSpecified() throws Exception
{
mockMvcFeedback.perform(MockMvcRequestBuilders.post(FeedbackController.URI).param("name", "First Last")
.param("subject", "Feedback form").param("email", "user@domain.com").param("feedback", "")
.param("captcha", "validCaptcha")).andExpect(status().is4xxClientError());
verify(captchaService, times(0)).validateCaptcha("validCaptcha");
}
@Test
public void submitErrorWhileSendingMail() throws Exception
{
MimeMessage message = mock(MimeMessage.class);
when(javaMailSender.createMimeMessage()).thenReturn(message);
List<String> adminEmails = Collections.singletonList("molgenis@molgenis.org");
when(userService.getSuEmailAddresses()).thenReturn(adminEmails);
doThrow(new MailSendException("ERRORRR!")).when(javaMailSender).send(message);
mockMvcFeedback.perform(MockMvcRequestBuilders.post(FeedbackController.URI).param("name", "First Last")
.param("subject", "Feedback form").param("email", "user@domain.com")
.param("feedback", "Feedback.\nLine two.").param("captcha", "validCaptcha")).andExpect(status().isOk())
.andExpect(view().name("view-feedback"))
.andExpect(model().attribute("feedbackForm", hasProperty("submitted", equalTo(false)))).andExpect(
model().attribute("feedbackForm", hasProperty("errorMessage",
equalTo("Unfortunately, we were unable to send the mail containing "
+ "your feedback. Please contact the administrator."))));
verify(captchaService, times(1)).validateCaptcha("validCaptcha");
}
@Test
public void submitInvalidCaptcha() throws Exception
{
when(captchaService.validateCaptcha("validCaptcha")).thenReturn(false);
mockMvcFeedback.perform(MockMvcRequestBuilders.post(FeedbackController.URI).param("name", "First Last")
.param("subject", "Feedback form").param("email", "user@domain.com")
.param("feedback", "Feedback.\nLine two.").param("captcha", "invalidCaptcha"))
.andExpect(status().isOk()).andExpect(view().name("view-feedback"))
.andExpect(model().attribute("feedbackForm", hasProperty("submitted", equalTo(false))))
.andExpect(model().attribute("feedbackForm", hasProperty("errorMessage", equalTo("Invalid captcha."))));
}
@ComponentScan({ "org.molgenis.auth" })
@Configuration
public static class Config
{
@Bean
public FeedbackController feedbackController()
{
return new FeedbackController(molgenisUserService(), appSettings(), captchaService(), mailSender());
}
@Bean
public UserService molgenisUserService()
{
return mock(UserService.class);
}
@Bean
public AppSettings appSettings()
{
return mock(AppSettings.class);
}
@Bean
public CaptchaService captchaService()
{
return mock(CaptchaService.class);
}
@Bean
public JavaMailSender mailSender()
{
return mock(JavaMailSender.class);
}
@Bean
public MolgenisPluginRegistry molgenisPluginRegistry()
{
return mock(MolgenisPluginRegistry.class);
}
@Bean
public DataService dataService()
{
return mock(DataService.class);
}
@Bean
public StaticContentService staticContentService()
{
return mock(StaticContentService.class);
}
}
}