/* documentr - Edit, maintain, and present software documentation on the web. Copyright (C) 2012-2013 Maik Schreiber This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.blizzy.documentr.web.attachment; import static de.blizzy.documentr.TestUtil.*; import static org.junit.Assert.*; import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.ui.Model; import org.springframework.web.multipart.MultipartFile; import de.blizzy.documentr.AbstractDocumentrTest; import de.blizzy.documentr.DocumentrConstants; import de.blizzy.documentr.access.User; import de.blizzy.documentr.access.UserStore; import de.blizzy.documentr.page.IPageStore; import de.blizzy.documentr.page.Page; import de.blizzy.documentr.page.PageMetadata; import de.blizzy.documentr.page.PageNotFoundException; import de.blizzy.documentr.page.TestPageUtil; public class AttachmentControllerTest extends AbstractDocumentrTest { private static final String PROJECT = "project"; //$NON-NLS-1$ private static final String BRANCH = "branch"; //$NON-NLS-1$ private static final String PAGE_PATH_URL = DocumentrConstants.HOME_PAGE_NAME + ",foo"; //$NON-NLS-1$ private static final String PAGE_PATH = DocumentrConstants.HOME_PAGE_NAME + "/foo"; //$NON-NLS-1$ private static final User USER = new User("currentUser", "pw", "admin@example.com", false); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ @Mock private IPageStore pageStore; @Mock private Authentication authentication; @Mock private ServletContext servletContext; @Mock private UserStore userStore; @Mock private Model model; @Mock private HttpServletRequest request; @Mock private HttpSession session; @Mock private MultipartFile multipartFile; @InjectMocks private AttachmentController attachmentController; @Before public void setUp() throws IOException { when(servletContext.getMimeType("test.png")).thenReturn("image/png"); //$NON-NLS-1$ //$NON-NLS-2$ when(userStore.getUser(USER.getLoginName())).thenReturn(USER); when(authentication.isAuthenticated()).thenReturn(true); when(authentication.getName()).thenReturn(USER.getLoginName()); } @Test public void getAttachments() { String view = attachmentController.getAttachments(PROJECT, BRANCH, PAGE_PATH_URL, model); assertEquals("/project/branch/page/attachments", view); //$NON-NLS-1$ verify(model).addAttribute("projectName", PROJECT); //$NON-NLS-1$ verify(model).addAttribute("branchName", BRANCH); //$NON-NLS-1$ verify(model).addAttribute("pagePath", PAGE_PATH); //$NON-NLS-1$ } @Test public void getAttachment() throws IOException { when(session.getAttribute("authenticationCreationTime")).thenReturn(System.currentTimeMillis()); //$NON-NLS-1$ when(request.getDateHeader(anyString())).thenReturn(-1L); when(request.getSession()).thenReturn(session); getAttachment(false, request); } @Test public void getAttachmentMustReturnNormallyIfModified() throws IOException { when(session.getAttribute("authenticationCreationTime")).thenReturn(System.currentTimeMillis()); //$NON-NLS-1$ when(request.getDateHeader("If-Modified-Since")).thenReturn( //$NON-NLS-1$ new GregorianCalendar(2000, Calendar.JANUARY, 1).getTimeInMillis()); when(request.getSession()).thenReturn(session); getAttachment(false, request); } @Test public void getAttachmentAsDownload() throws IOException { when(session.getAttribute("authenticationCreationTime")).thenReturn(System.currentTimeMillis()); //$NON-NLS-1$ when(request.getDateHeader(anyString())).thenReturn(-1L); when(request.getSession()).thenReturn(session); getAttachment(true, request); } private void getAttachment(boolean download, HttpServletRequest request) throws IOException { when(pageStore.getAttachmentMetadata(PROJECT, BRANCH, PAGE_PATH, "test.png")) //$NON-NLS-1$ .thenReturn(new PageMetadata("user", new Date(), 123, "commit")); //$NON-NLS-1$ //$NON-NLS-2$ byte[] data = { 1, 2, 3 }; String contentType = "image/png"; //$NON-NLS-1$ Page attachment = Page.fromData(data, contentType); when(pageStore.getAttachment(PROJECT, BRANCH, PAGE_PATH, "test.png")).thenReturn(attachment); //$NON-NLS-1$ SecurityContextHolder.setContext(createSecurityContext(authentication)); ResponseEntity<byte[]> result = attachmentController.getAttachment( PROJECT, BRANCH, PAGE_PATH_URL, "test.png", download, request); //$NON-NLS-1$ SecurityContextHolder.clearContext(); assertTrue(Arrays.equals(data, result.getBody())); assertEquals(MediaType.parseMediaType(contentType), result.getHeaders().getContentType()); assertEquals(HttpStatus.OK, result.getStatusCode()); if (download) { assertEquals("attachment; filename=\"test.png\"", //$NON-NLS-1$ result.getHeaders().getFirst("Content-Disposition")); //$NON-NLS-1$ } } @Test public void getAttachmentMustReturn404IfNotFound() throws IOException { when(request.getDateHeader(anyString())).thenReturn(-1L); when(pageStore.getAttachmentMetadata(PROJECT, BRANCH, PAGE_PATH, "test.png")) //$NON-NLS-1$ .thenThrow(new PageNotFoundException(PROJECT, BRANCH, PAGE_PATH + "/test.png")); //$NON-NLS-1$ ResponseEntity<byte[]> result = attachmentController.getAttachment( PROJECT, BRANCH, PAGE_PATH_URL, "test.png", false, request); //$NON-NLS-1$ assertEquals(HttpStatus.NOT_FOUND, result.getStatusCode()); } @Test public void getAttachmentMustReturn304IfNotModified() throws IOException { when(session.getAttribute("authenticationCreationTime")).thenReturn( //$NON-NLS-1$ new GregorianCalendar(2012, Calendar.JUNE, 1).getTime().getTime()); when(request.getDateHeader("If-Modified-Since")).thenReturn( //$NON-NLS-1$ new GregorianCalendar(2012, Calendar.JUNE, 9).getTimeInMillis()); when(request.getSession()).thenReturn(session); when(pageStore.getAttachmentMetadata(PROJECT, BRANCH, PAGE_PATH, "test.png")) //$NON-NLS-1$ .thenReturn(new PageMetadata("user", new GregorianCalendar(2012, Calendar.JUNE, 1).getTime(), 123, "commit")); //$NON-NLS-1$ //$NON-NLS-2$ TestPageUtil.clearProjectEditTimes(); ResponseEntity<byte[]> result = attachmentController.getAttachment( PROJECT, BRANCH, PAGE_PATH_URL, "test.png", false, request); //$NON-NLS-1$ assertEquals(HttpStatus.NOT_MODIFIED, result.getStatusCode()); } @Test public void createAttachment() { String view = attachmentController.createAttachment(PROJECT, BRANCH, PAGE_PATH_URL, model); assertEquals("/project/branch/page/editAttachment", view); //$NON-NLS-1$ verify(model).addAttribute("projectName", PROJECT); //$NON-NLS-1$ verify(model).addAttribute("branchName", BRANCH); //$NON-NLS-1$ verify(model).addAttribute("pagePath", PAGE_PATH); //$NON-NLS-1$ } @Test public void saveAttachment() throws IOException { byte[] data = { 1, 2, 3 }; InputStream inputStream = new ByteArrayInputStream(data); when(multipartFile.getInputStream()).thenReturn(inputStream); when(multipartFile.getOriginalFilename()).thenReturn("test.png"); //$NON-NLS-1$ String view = attachmentController.saveAttachment(PROJECT, BRANCH, PAGE_PATH_URL, multipartFile, authentication); assertEquals("/attachment/list/" + PROJECT + "/" + BRANCH + "/" + PAGE_PATH_URL, removeViewPrefix(view)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ assertRedirect(view); Page attachment = Page.fromData(data, "image/png"); //$NON-NLS-1$ verify(pageStore).saveAttachment(PROJECT, BRANCH, PAGE_PATH, "test.png", attachment, USER); //$NON-NLS-1$ } @Test public void saveAttachmentMustUseDefaultContentTypeIfUnknown() throws IOException { byte[] data = { 1, 2, 3 }; InputStream inputStream = new ByteArrayInputStream(data); when(multipartFile.getInputStream()).thenReturn(inputStream); when(multipartFile.getOriginalFilename()).thenReturn("test.dat"); //$NON-NLS-1$ String view = attachmentController.saveAttachment(PROJECT, BRANCH, PAGE_PATH_URL, multipartFile, authentication); assertEquals("/attachment/list/" + PROJECT + "/" + BRANCH + "/" + PAGE_PATH_URL, removeViewPrefix(view)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ assertRedirect(view); Page attachment = Page.fromData(data, DocumentrConstants.DEFAULT_MIME_TYPE); verify(pageStore).saveAttachment(PROJECT, BRANCH, PAGE_PATH, "test.dat", attachment, USER); //$NON-NLS-1$ } @Test public void deleteAttachment() throws IOException { String view = attachmentController.deleteAttachment(PROJECT, BRANCH, PAGE_PATH_URL, "test.dat", authentication); //$NON-NLS-1$ assertEquals("/attachment/list/" + PROJECT + "/" + BRANCH + "/" + PAGE_PATH_URL, removeViewPrefix(view)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ assertRedirect(view); verify(pageStore).deleteAttachment(PROJECT, BRANCH, PAGE_PATH, "test.dat", USER); //$NON-NLS-1$ } }