package ca.intelliware.ihtsdo.mlds.web.rest; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.util.Arrays; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.util.NestedServletException; import ca.intelliware.ihtsdo.mlds.domain.Affiliate; import ca.intelliware.ihtsdo.mlds.domain.AffiliateDetails; import ca.intelliware.ihtsdo.mlds.domain.AffiliateType; import ca.intelliware.ihtsdo.mlds.domain.Application; import ca.intelliware.ihtsdo.mlds.domain.ApprovalState; import ca.intelliware.ihtsdo.mlds.domain.CommercialUsage; import ca.intelliware.ihtsdo.mlds.domain.Country; import ca.intelliware.ihtsdo.mlds.domain.Member; import ca.intelliware.ihtsdo.mlds.domain.PrimaryApplication; import ca.intelliware.ihtsdo.mlds.domain.StandingState; import ca.intelliware.ihtsdo.mlds.domain.UsageReportState; import ca.intelliware.ihtsdo.mlds.repository.AffiliateDetailsRepository; import ca.intelliware.ihtsdo.mlds.repository.AffiliateRepository; import ca.intelliware.ihtsdo.mlds.repository.ApplicationRepository; import ca.intelliware.ihtsdo.mlds.repository.CountryRepository; import ca.intelliware.ihtsdo.mlds.repository.MemberRepository; import ca.intelliware.ihtsdo.mlds.repository.UserRepository; import ca.intelliware.ihtsdo.mlds.service.AffiliateAuditEvents; import ca.intelliware.ihtsdo.mlds.service.AffiliateDetailsResetter; import ca.intelliware.ihtsdo.mlds.service.ApplicationService; import ca.intelliware.ihtsdo.mlds.service.CommercialUsageService; import ca.intelliware.ihtsdo.mlds.service.UsageReportTransition; import ca.intelliware.ihtsdo.mlds.service.mail.ApplicationApprovedEmailSender; import ca.intelliware.ihtsdo.mlds.web.RouteLinkBuilder; import ca.intelliware.ihtsdo.mlds.web.SessionService; public class ApplicationResource_SubmitApplication_Test { private MockMvc mockMvc; @Mock ApplicationRepository applicationRepository; @Mock ApplicationAuditEvents applicationAuditEvents; @Mock ApplicationAuthorizationChecker applicationAuthorizationChecker; @Mock MemberRepository memberRepository; @Mock CountryRepository countryRepository; @Mock ApplicationService applicationService; @Mock AffiliateRepository affiliateRepository; @Mock AffiliateDetailsRepository affiliateDetailsRepository; @Mock AffiliateDetailsResetter affiliateDetailsResetter; @Mock AffiliateAuditEvents affiliateAuditEvents; @Mock UserRepository userRepository; @Mock SessionService sessionService; @Mock ApplicationApprovedEmailSender applicationApprovedEmailSender; @Mock ApplicationApprovalStateChangeNotifier applicationApprovalStateChangeNotifier; @Mock CommercialUsageService commercialUsageService; ApplicationResource applicationResource; Member swedenMember; Country sweden; @Before public void setup() { MockitoAnnotations.initMocks(this); applicationResource = new ApplicationResource(); applicationResource.applicationRepository = applicationRepository; applicationResource.applicationAuditEvents = applicationAuditEvents; applicationResource.authorizationChecker = applicationAuthorizationChecker; applicationResource.applicationService = applicationService; applicationResource.memberRepository = memberRepository; applicationResource.countryRepository = countryRepository; applicationResource.affiliateRepository = affiliateRepository; applicationResource.affiliateDetailsRepository = affiliateDetailsRepository; applicationResource.affiliateDetailsResetter = affiliateDetailsResetter; applicationResource.affiliateAuditEvents = affiliateAuditEvents; applicationResource.userRepository = userRepository; applicationResource.applicationApprovedEmailSender = applicationApprovedEmailSender; applicationResource.applicationApprovalStateChangeNotifier = applicationApprovalStateChangeNotifier; applicationResource.sessionService = sessionService; applicationResource.commercialUsageService = commercialUsageService; applicationResource.routeLinkBuilder = new RouteLinkBuilder(); this.mockMvc = MockMvcBuilders .standaloneSetup(applicationResource) .setMessageConverters(new MockMvcJacksonTestSupport().getConfiguredMessageConverters()) .build(); swedenMember = new Member("SE", 1); Mockito.when(memberRepository.findOneByKey("SE")).thenReturn(swedenMember); sweden = new Country("SE", "SWE", "Sweden"); sweden.setMember(swedenMember); Mockito.when(countryRepository.findOne("SE")).thenReturn(sweden); Mockito.when(sessionService.getUsernameOrNull()).thenReturn("user"); } @Test public void submitApplicationShouldFailForUnknownApplication() throws Exception { Affiliate affiliate = withAffiliate(StandingState.APPLYING, AffiliateType.ACADEMIC); postSubmitApplication(1L, applicationRequestBody()) .andExpect(status().isNotFound()); } @Test public void submitApplicationShouldFailIfCheckerDenies() throws Exception { Affiliate affiliate = withAffiliate(StandingState.APPLYING, AffiliateType.ACADEMIC); PrimaryApplication application = withExistingSwedishPrimaryApplication(1L, affiliate); application.setApprovalState(ApprovalState.NOT_SUBMITTED); application.getCommercialUsage().setState(UsageReportState.NOT_SUBMITTED); Mockito.doThrow(new IllegalStateException("NO_ACCESS")).when(applicationAuthorizationChecker).checkCanAccessApplication(Mockito.any(Application.class)); try { postSubmitApplication(1L, applicationRequestBody()) .andExpect(status().is5xxServerError()); Assert.fail(); } catch (NestedServletException e) { Assert.assertThat(e.getRootCause().getMessage(), Matchers.containsString("NO_ACCESS")); } } @Test public void submitApplicationShouldPromoteApplicationToSubmitted() throws Exception { Affiliate affiliate = withAffiliate(StandingState.APPLYING, AffiliateType.ACADEMIC); PrimaryApplication application = withExistingSwedishPrimaryApplication(1L, affiliate); application.setApprovalState(ApprovalState.NOT_SUBMITTED); application.getCommercialUsage().setState(UsageReportState.NOT_SUBMITTED); postSubmitApplication(1L, applicationRequestBody()) .andExpect(status().isOk()); Assert.assertEquals(ApprovalState.SUBMITTED, application.getApprovalState()); } @Test public void submitApplicationShouldRefuseIllegalTransformation() throws Exception { Affiliate affiliate = withAffiliate(StandingState.APPLYING, AffiliateType.ACADEMIC); PrimaryApplication application = withExistingSwedishPrimaryApplication(1L, affiliate); application.setApprovalState(ApprovalState.SUBMITTED); application.getCommercialUsage().setState(UsageReportState.SUBMITTED); postSubmitApplication(1L, applicationRequestBody()) .andExpect(status().isConflict()); } @Test public void submitApplicationShouldLogSubmit() throws Exception { Affiliate affiliate = withAffiliate(StandingState.APPLYING, AffiliateType.ACADEMIC); PrimaryApplication application = withExistingSwedishPrimaryApplication(1L, affiliate); application.setApprovalState(ApprovalState.NOT_SUBMITTED); application.getCommercialUsage().setState(UsageReportState.NOT_SUBMITTED); postSubmitApplication(1L, applicationRequestBody()) .andExpect(status().isOk()); Mockito.verify(applicationAuditEvents).logApprovalStateChange(Mockito.any(Application.class)); } @Test public void submitApplicationShouldNotifyUser() throws Exception { Affiliate affiliate = withAffiliate(StandingState.APPLYING, AffiliateType.ACADEMIC); PrimaryApplication application = withExistingSwedishPrimaryApplication(1L, affiliate); application.setApprovalState(ApprovalState.NOT_SUBMITTED); application.getCommercialUsage().setState(UsageReportState.NOT_SUBMITTED); postSubmitApplication(1L, applicationRequestBody()) .andExpect(status().isOk()); ArgumentCaptor<Application> applicationCaptor = ArgumentCaptor.forClass(Application.class); Mockito.verify(applicationApprovalStateChangeNotifier).applicationApprovalStateChange(Mockito.eq(ApprovalState.NOT_SUBMITTED), applicationCaptor.capture()); assertThat(applicationCaptor.getValue().getApprovalState(), equalTo(ApprovalState.SUBMITTED)); } private String applicationRequestBody() { return "{\"applicationId\":1, \"affiliateDetails\":{\"address\":{\"country\":{\"isoCode2\":\"SE\"}}, \"billingAddress\":{}}}"; } @Test public void submitApplicationShouldTransitionApprovalForNonCommercialSubmission() throws Exception { Affiliate affiliate = withAffiliate(StandingState.APPLYING, AffiliateType.ACADEMIC); PrimaryApplication application = withExistingSwedishPrimaryApplication(1L, affiliate); application.setApprovalState(ApprovalState.NOT_SUBMITTED); application.getCommercialUsage().setState(UsageReportState.NOT_SUBMITTED); postSubmitApplication(1L, applicationRequestBody()) .andExpect(status().isOk()); Mockito.verify(commercialUsageService).transitionCommercialUsageApproval(Mockito.any(CommercialUsage.class), Mockito.eq(UsageReportTransition.SUBMIT)); } @Test public void submitApplicationShouldNotTransitionApprovalForAlreadySubmittedSubmission() throws Exception { Affiliate affiliate = withAffiliate(StandingState.APPLYING, AffiliateType.ACADEMIC); PrimaryApplication application = withExistingSwedishPrimaryApplication(1L, affiliate); application.setApprovalState(ApprovalState.CHANGE_REQUESTED); application.getCommercialUsage().setState(UsageReportState.SUBMITTED); postSubmitApplication(1L, applicationRequestBody()) .andExpect(status().isOk()); Mockito.verify(commercialUsageService, Mockito.never()).transitionCommercialUsageApproval(Mockito.any(CommercialUsage.class), Mockito.any(UsageReportTransition.class)); } private ResultActions postSubmitApplication(long primaryApplicationId, String updatedApprovalState) throws Exception { return mockMvc.perform( MockMvcRequestBuilders .post(Routes.APPLICATION_REGISTRATION, primaryApplicationId) .contentType(MediaType.APPLICATION_JSON) .content(updatedApprovalState) .accept(MediaType.APPLICATION_JSON)); } private PrimaryApplication withExistingSwedishPrimaryApplication(long primaryApplicationId, Affiliate affiliate) { PrimaryApplication primaryApplication = new PrimaryApplication(primaryApplicationId); primaryApplication.setAffiliateDetails(new AffiliateDetails()); primaryApplication.setMember(swedenMember); primaryApplication.setAffiliate(affiliate); CommercialUsage commercialUsage = new CommercialUsage(10L, affiliate); commercialUsage.setType(affiliate.getType()); primaryApplication.setCommercialUsage(commercialUsage); Mockito.when(applicationRepository.findOne(primaryApplicationId)).thenReturn(primaryApplication); return primaryApplication; } private Affiliate withAffiliate(StandingState existingStandingState, AffiliateType affiliateType) { Affiliate affiliate = new Affiliate(2L); affiliate.setStandingState(existingStandingState); affiliate.setAffiliateDetails(new AffiliateDetails()); affiliate.setType(affiliateType); Mockito.when(affiliateRepository.findByCreatorIgnoreCase(Mockito.anyString())).thenReturn(Arrays.asList(affiliate)); return affiliate; } }