/*
 * MIT Licence
 * Copyright (c) 2020 Simon Frankenberger
 *
 * Please see LICENCE.md for complete licence text.
 */
package eu.fraho.spring.securityJwt.tests.ut;

import eu.fraho.spring.securityJwt.base.JwtAuthenticationTokenFilter;
import eu.fraho.spring.securityJwt.base.dto.JwtUser;
import eu.fraho.spring.securityJwt.base.service.JwtTokenService;
import eu.fraho.spring.securityJwt.base.service.JwtTokenServiceImpl;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.security.core.context.SecurityContextHolder;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;

public class JwtAuthenticationTokenFilterTest {
    protected JwtTokenService getService() {
        return Mockito.mock(JwtTokenServiceImpl.class);
    }

    private JwtAuthenticationTokenFilter getNewInstance(JwtTokenService jwtTokenService) {
        JwtAuthenticationTokenFilter filter = new JwtAuthenticationTokenFilter();
        filter.setJwtTokenService(jwtTokenService);
        return filter;
    }

    @BeforeEach
    public void cleanSecurityContext() {
        SecurityContextHolder.getContext().setAuthentication(null);
    }

    @Test
    public void testRegularAuthentication() throws ServletException, IOException {
        JwtTokenService service = getService();
        Mockito.when(service.getAccessToken(Mockito.any())).thenReturn(Optional.of("foobar"));
        Mockito.when(service.parseUser(Mockito.any())).thenReturn(Optional.of(new JwtUser()));

        FilterChain chain = Mockito.mock(FilterChain.class);
        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        JwtAuthenticationTokenFilter instance = getNewInstance(service);

        instance.doFilter(request, response, chain);
        Mockito.verify(chain).doFilter(request, response);

        Assertions.assertNotNull(SecurityContextHolder.getContext().getAuthentication(), "Authentication failed");
    }

    @Test
    public void testNoTokenPresent() throws ServletException, IOException {
        JwtTokenService service = getService();
        Mockito.when(service.getAccessToken(Mockito.any())).thenReturn(Optional.empty());

        FilterChain chain = Mockito.mock(FilterChain.class);
        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        JwtAuthenticationTokenFilter instance = getNewInstance(service);

        instance.doFilter(request, response, chain);
        Mockito.verify(chain).doFilter(request, response);

        Assertions.assertNull(SecurityContextHolder.getContext().getAuthentication(), "Authentication succeeded");
    }

    @Test
    public void testParseFailed() throws ServletException, IOException {
        JwtTokenService service = getService();
        Mockito.when(service.getAccessToken(Mockito.any())).thenReturn(Optional.of("foobar"));
        Mockito.when(service.parseUser(Mockito.any())).thenReturn(Optional.empty());

        FilterChain chain = Mockito.mock(FilterChain.class);
        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        JwtAuthenticationTokenFilter instance = getNewInstance(service);

        instance.doFilter(request, response, chain);
        Mockito.verify(chain).doFilter(request, response);

        Assertions.assertNull(SecurityContextHolder.getContext().getAuthentication(), "Authentication succeeded");
    }
}

@@ -820,32 +820,65 @@
 io.IOException;%0A
+import java.lang.reflect.Method;%0A
 import java.util
@@ -888,16 +888,16 @@
 tional;%0A
-
 %0Apublic 
@@ -1514,32 +1514,62 @@
 ion, IOException
+, ReflectiveOperationException
  %7B%0A        JwtTo
@@ -2094,34 +2094,246 @@
         
-instance.doFilter(
+Method method = JwtAuthenticationTokenFilter.class.getDeclaredMethod(%22doFilterInternal%22, HttpServletRequest.class, HttpServletResponse.class, FilterChain.class);%0A        method.setAccessible(true);%0A        method.invoke(instance, 
 request,
@@ -2608,32 +2608,62 @@
 ion, IOException
+, ReflectiveOperationException
  %7B%0A        JwtTo
@@ -3088,34 +3088,246 @@
         
-instance.doFilter(
+Method method = JwtAuthenticationTokenFilter.class.getDeclaredMethod(%22doFilterInternal%22, HttpServletRequest.class, HttpServletResponse.class, FilterChain.class);%0A        method.setAccessible(true);%0A        method.invoke(instance, 
 request,
@@ -3599,32 +3599,62 @@
 ion, IOException
+, ReflectiveOperationException
  %7B%0A        JwtTo
@@ -4173,26 +4173,238 @@
     
-instance.doFilter(
+Method method = JwtAuthenticationTokenFilter.class.getDeclaredMethod(%22doFilterInternal%22, HttpServletRequest.class, HttpServletResponse.class, FilterChain.class);%0A        method.setAccessible(true);%0A        method.invoke(instance, 
 requ

fix JwtAuthenticationTokenFilterTest