package com.googlecode.tawus.ajaxupload.components; import java.util.ArrayList; import java.util.List; import java.util.Vector; import org.apache.tapestry5.BaseValidationDecorator; import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.Field; import org.apache.tapestry5.FieldValidationSupport; import org.apache.tapestry5.FieldValidator; import org.apache.tapestry5.Link; import org.apache.tapestry5.MarkupWriter; import org.apache.tapestry5.ValidationDecorator; import org.apache.tapestry5.ValidationException; import org.apache.tapestry5.dom.Element; import org.apache.tapestry5.ioc.Messages; import org.apache.tapestry5.json.JSONArray; import org.apache.tapestry5.json.JSONObject; import org.apache.tapestry5.services.FormSupport; import org.apache.tapestry5.services.Request; import org.apache.tapestry5.test.TapestryTestCase; import org.apache.tapestry5.upload.services.MultipartDecoder; import org.apache.tapestry5.upload.services.UploadedFile; import org.testng.annotations.Test; import com.googlecode.tawus.ajaxupload.AjaxUploadConstants; import com.googlecode.tawus.ajaxupload.services.AjaxUploadDecoder; public class AjaxUploadTest extends TapestryTestCase { @Test public void upload_is_field() throws Exception { assertTrue(Field.class.isAssignableFrom(AjaxUpload.class)); } @Test public void begin_render_writes_input_tag() { MarkupWriter writer = createMarkupWriter(); writer.element("form"); FormSupport formSupport = mockFormSupport(); ComponentResources resources = mockComponentResources(); @SuppressWarnings("unchecked") FieldValidator<Object> validator = mockFieldValidator(); Request request = mockRequest(); validator.render(writer); replay(); AjaxUpload component = new AjaxUpload(null, null, null, null, null, resources, null, null); component.injectDecorator(new BaseValidationDecorator()).injectFormSupport(formSupport).injectFieldValidator( validator).injectRequest(request); component.beginRender(writer); Element element = writer.getElement(); assertNotNull(element); assertEquals(element.getName(), "input"); verify(); } @Test public void begin_render_invokes_field_validator() throws Exception { getMocksControl().checkOrder(true); @SuppressWarnings("unchecked") FieldValidator<Object> validate = mockFieldValidator(); ComponentResources resources = mockComponentResources(); AjaxUpload component = new AjaxUpload(null, validate, null, null, null, resources, null, null); MarkupWriter writer = createMarkupWriter(); writer.element("form"); Request request = mockRequest(); FormSupport formSupport = mockFormSupport(); ValidationDecorator decorator = mockValidationDecorator(); component.injectDecorator(decorator).injectRequest(request).injectFormSupport(formSupport); validate.render(writer); decorator.insideField(component); replay(); component.beginRender(writer); verify(); } @Test public void after_render_closes_element() { ComponentResources resources = mockComponentResources(); AjaxUpload component = new AjaxUpload(null, null, null, null, null, resources, null, null); MarkupWriter writer = mockMarkupWriter(); expect(writer.end()).andReturn(null).times(2); expect(writer.element("span", "id", "null_wrapper", "style", "display:inline-block")).andReturn(null); replay(); component.afterRender(writer); verify(); } @Test public void check_upload_link() { ComponentResources resources = mockComponentResources(); AjaxUpload component = new AjaxUpload(); component.injectValue(new Vector<UploadedFile>()); component.injectResources(resources); setupCreateEventLink(resources, "upload", "uploadLink"); replay(); assertEquals(component.getUploadLink(), "uploadLink"); verify(); } @Test public void check_js_cancel_function() { ComponentResources resources = mockComponentResources(); AjaxUpload component = new AjaxUpload(); component.injectValue(new Vector<UploadedFile>()); component.injectResources(resources); setupCreateEventLink(resources, "cancelUpload", "cancelUploadLink"); replay(); assertEquals(component.getCancelLink(), "cancelUploadLink"); verify(); } @Test public void check_js_remove_function() { ComponentResources resources = mockComponentResources(); AjaxUpload component = new AjaxUpload(); component.injectValue(new Vector<UploadedFile>()); component.injectResources(resources); setupCreateEventLink(resources, "removeUpload", "removeUploadLink"); replay(); assertEquals(component.getRemoveLink(), "removeUploadLink"); verify(); } @Test public void check_current_upload_list() { AjaxUpload component = new AjaxUpload(); List<UploadedFile> value = new ArrayList<UploadedFile>(); UploadedFile uploadedFile = mockUploadedFile(); value.add(uploadedFile); expect(uploadedFile.getFilePath()).andReturn("test"); component.injectValue(value); replay(); JSONArray array = ((JSONObject)component.onInitializeUploads()).getJSONArray("uploads"); assertEquals(array.length(), 1); assertTrue(array.get(0) instanceof JSONObject); JSONObject element = (JSONObject) array.get(0); assertEquals(element.get("serverIndex"), 0); assertEquals(element.get("fileName"), "test"); verify(); } private void setupCreateEventLink(ComponentResources resources, String event, String url) { Link link = mockLink(); expect(link.toAbsoluteURI()).andReturn(url); expect(resources.createEventLink(event)).andReturn(link); } @Test public void check_upload_calls_ajax_decoder_for_ajax_upload() throws Exception { AjaxUploadDecoder ajaxDecoder = mockAjaxUploadDecoder(); UploadedFile uploadedFile = mockUploadedFile(); Request request = mockRequest(); AjaxUpload component = new AjaxUpload(null, null, null, ajaxDecoder, null, null, null, null); component.injectRequest(request); expect(request.isXHR()).andReturn(true).anyTimes(); expect(ajaxDecoder.getFileUpload()).andReturn(uploadedFile); expect(ajaxDecoder.isAjaxUploadRequest(request)).andReturn(true); replay(); Object response = component.onUpload(); assertTrue(response instanceof JSONObject); JSONObject responseJSON = (JSONObject) response; assertTrue((Boolean) responseJSON.get("success")); assertEquals((Integer) responseJSON.get("serverIndex"), new Integer(0)); verify(); assertEquals(component.getValue().size(), 1); assertSame(component.getValue().get(0), uploadedFile); } @Test public void check_upload_calls_multipart_decoder_for_non_ajax_upload() throws Exception { MultipartDecoder multipartDecoder = mockMultipartDecoder(); AjaxUploadDecoder ajaxDecoder = mockAjaxUploadDecoder(); UploadedFile uploadedFile = mockUploadedFile(); Request request = mockRequest(); AjaxUpload component = new AjaxUpload(null, null, multipartDecoder, ajaxDecoder, null, null, null, null); component.injectRequest(request); expect(request.isXHR()).andReturn(false).anyTimes(); expect(ajaxDecoder.isAjaxUploadRequest(request)).andReturn(false); expect(multipartDecoder.getFileUpload(AjaxUploadConstants.FILE_PARAMETER)).andReturn(uploadedFile); replay(); Object response = component.onUpload(); assertTrue(response instanceof AjaxUpload.StatusResponse); JSONObject responseJSON = ((AjaxUpload.StatusResponse) response).getJSON(); assertTrue((Boolean) responseJSON.get("success")); assertEquals((Integer) responseJSON.get("serverIndex"), new Integer(0)); verify(); assertEquals(component.getValue().size(), 1); assertSame(component.getValue().get(0), uploadedFile); } @Test public void check_upload_fails_if_max_file_count_is_reached() throws Exception { AjaxUploadDecoder ajaxDecoder = mockAjaxUploadDecoder(); UploadedFile uploadedFile = mockUploadedFile(); Request request = mockRequest(); AjaxUpload component = new AjaxUpload(null, null, null, ajaxDecoder, null, null, null, null); component.injectRequest(request); List<UploadedFile> value = new ArrayList<UploadedFile>(); value.add(uploadedFile); component.injectValue(value); Messages messages = mockMessages(); expect(messages.format("ajaxupload.maxfiles", 1)).andReturn("Max files reached"); component.injectMessages(messages); expect(request.isXHR()).andReturn(true).anyTimes(); replay(); JSONObject response = (JSONObject) component.onUpload(); verify(); assertFalse((Boolean) response.get("success")); assertEquals((String) response.get("error"), "Max files reached"); } @Test public void check_on_remove_works_for_null_value() { AjaxUpload component = new AjaxUpload(); component.injectValue(new Vector<UploadedFile>()); component.onRemoveUpload(0); } @Test public void check_on_remove_works_for_boundary_values() { AjaxUpload component = new AjaxUpload(); // Set 2 elements List<UploadedFile> uploadedFiles = new Vector<UploadedFile>(); uploadedFiles.add(mockUploadedFile()); uploadedFiles.add(mockUploadedFile()); component.injectValue(uploadedFiles); component.onRemoveUpload(-1); component.onRemoveUpload(0); component.onRemoveUpload(1); component.onRemoveUpload(2); component.onRemoveUpload(3); } @Test public void check_on_remove_works_if_same_value_is_removed_twice() { AjaxUpload component = new AjaxUpload(); // Set 2 elements List<UploadedFile> uploadedFiles = new ArrayList<UploadedFile>(); uploadedFiles.add(mockUploadedFile()); uploadedFiles.add(mockUploadedFile()); component.injectValue(uploadedFiles); component.onRemoveUpload(1); component.onRemoveUpload(1); // Assert the size stays same assertEquals(component.getValue().size(), 2); } @Test public void check_after_removal_process_submission_removes_all_null_values_from_list() throws ValidationException { ComponentResources resources = mockComponentResources(); FieldValidationSupport support = mockFieldValidationSupport(); @SuppressWarnings("unchecked") FieldValidator<Object> validate = mockFieldValidator(); AjaxUpload component = new AjaxUpload(null, validate, null, null, null, resources, support, null); // Set 2 elements List<UploadedFile> uploadedFiles = new ArrayList<UploadedFile>(); uploadedFiles.add(mockUploadedFile()); uploadedFiles.add(mockUploadedFile()); component.injectValue(uploadedFiles); component.onRemoveUpload(1); // Assert the size stays same assertEquals(component.getValue().size(), 2); component.processSubmission("test"); assertEquals(component.getValue().size(), 1); } protected final UploadedFile mockUploadedFile() { return newMock(UploadedFile.class); } protected final MultipartDecoder mockMultipartDecoder() { return newMock(MultipartDecoder.class); } protected final AjaxUploadDecoder mockAjaxUploadDecoder() { return newMock(AjaxUploadDecoder.class); } }