/******************************************************************************* * Copyright (c) 2012, 2015 EclipseSource and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * EclipseSource - initial API and implementation ******************************************************************************/ package org.eclipse.rap.rwt.internal.resources; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.List; import org.eclipse.rap.json.JsonArray; import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.client.WebClient; import org.eclipse.rap.rwt.internal.protocol.Operation; import org.eclipse.rap.rwt.internal.protocol.Operation.CallOperation; import org.eclipse.rap.rwt.internal.protocol.Operation.CreateOperation; import org.eclipse.rap.rwt.internal.service.ContextProvider; import org.eclipse.rap.rwt.service.ResourceManager; import org.eclipse.rap.rwt.testfixture.internal.Fixture; import org.eclipse.rap.rwt.testfixture.internal.TestMessage; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.junit.After; import org.junit.Before; import org.junit.Test; public class JavaScriptModuleLoaderImpl_Test { private static final String JS_FILE_1 = "resourcetest1.js"; private static final String JS_FILE_2 = "utf-8-resource.js"; private final JavaScriptModuleLoader loader = new JavaScriptModuleLoaderImpl(); private ResourceManager resourceManager; private Display display; @Before public void setUp() { Fixture.setUp(); display = new Display(); Fixture.fakeNewRequest(); resourceManager = RWT.getResourceManager(); } @After public void tearDown() { Fixture.tearDown(); } @Test public void testRegisterOnce() { ensureFiles( new String[]{ JS_FILE_1 } ); String expected = getRegistryPath() + "/resourcetest1.js"; assertTrue( resourceManager.isRegistered( expected ) ); } @Test public void testDoNotRegisterTwice() { ensureFiles( new String[]{ JS_FILE_1 } ); ensureFiles( new String[]{ JS_FILE_2 } ); // Same module, different return value: not a valid use case! // Used to check for repeated registration String expected = getRegistryPath() + "/" + JS_FILE_1; String notExpected = getRegistryPath() + "/" + JS_FILE_2; assertTrue( resourceManager.isRegistered( expected ) ); assertFalse( resourceManager.isRegistered( notExpected ) ); } @Test public void testRegisterMultipleFiles() { ensureFiles( new String[]{ JS_FILE_1, JS_FILE_2 } ); String expectedOne = getRegistryPath() + "/" + JS_FILE_1; String expectedTwo = getRegistryPath() + "/" + JS_FILE_2; assertTrue( resourceManager.isRegistered( expectedOne ) ); assertTrue( resourceManager.isRegistered( expectedTwo ) ); } @Test public void testRegisterMultipleModules() { ensureFiles( new String[]{ JS_FILE_1 } ); ensureFiles( new String[]{ JS_FILE_2 }, true ); String expectedOne = getRegistryPath( false ) + "/" + JS_FILE_1; String expectedTwo = getRegistryPath( true ) + "/" + JS_FILE_2; assertTrue( resourceManager.isRegistered( expectedOne ) ); assertTrue( resourceManager.isRegistered( expectedTwo ) ); } @Test public void testFileNotFound() { try { ensureFiles( new String[]{ "this-file-does-not-exist.js" } ); fail(); } catch( Exception ex ) { // expected } } @Test public void testNoFilesGiven() { try { ensureFiles( new String[]{} ); fail(); } catch( Exception ex ) { // expected } } @Test public void testLoadOnce() { ensureFiles( new String[]{ JS_FILE_1 } ); Fixture.executeLifeCycleFromServerThread(); TestMessage message = Fixture.getProtocolMessage(); String expected = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1; assertNotNull( findLoadOperation( message, expected ) ); } @Test public void testLoadBeforeCreateWidget() { ensureFiles( new String[]{ JS_FILE_1 } ); Shell shell = new Shell( display ); Fixture.executeLifeCycleFromServerThread(); TestMessage message = Fixture.getProtocolMessage(); CreateOperation createOperation = message.findCreateOperation( shell ); String expected = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1; CallOperation loadOperation = findLoadOperation( message, expected ); List<Operation> operations = message.getOperations(); assertTrue( operations.indexOf( loadOperation ) < operations.indexOf( createOperation ) ); } @Test public void testDoNotLoadTwiceForSameRequest() { ensureFiles( new String[]{ JS_FILE_1 } ); ensureFiles( new String[]{ JS_FILE_1 } ); Fixture.executeLifeCycleFromServerThread(); TestMessage message = Fixture.getProtocolMessage(); String file = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1; assertEquals( 1, findLoadOperations( message, file ).length ); } @Test public void testDoNotLoadTwiceForSameSession() { ensureFiles( new String[]{ JS_FILE_1 } ); Fixture.executeLifeCycleFromServerThread(); Fixture.fakeNewRequest(); ensureFiles( new String[]{ JS_FILE_1 } ); Fixture.executeLifeCycleFromServerThread(); TestMessage message = Fixture.getProtocolMessage(); String expected = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1; assertNull( findLoadOperation( message, expected ) ); } @Test public void testDoLoadTwiceForSameApplication() { ensureFiles( new String[]{ JS_FILE_1 } ); Fixture.executeLifeCycleFromServerThread(); newSession(); ensureFiles( new String[]{ JS_FILE_1 } ); Fixture.executeLifeCycleFromServerThread(); TestMessage message = Fixture.getProtocolMessage(); String expected = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1; assertNotNull( findLoadOperation( message, expected ) ); } @Test public void testLoadMultipleFiles() { ensureFiles( new String[]{ JS_FILE_1, JS_FILE_2 } ); Fixture.executeLifeCycleFromServerThread(); TestMessage message = Fixture.getProtocolMessage(); String expectedOne = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1; String expectedTwo = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_2; CallOperation operationOne = findLoadOperation( message, expectedOne ); CallOperation operationTwo = findLoadOperation( message, expectedTwo ); assertNotNull( operationOne ); List<Operation> operations = message.getOperations(); assertEquals( operations.indexOf( operationOne ), operations.indexOf( operationTwo ) ); } @Test public void testLoadMultipleFilesInOrder() { ensureFiles( new String[]{ JS_FILE_1, JS_FILE_2 } ); Fixture.executeLifeCycleFromServerThread(); TestMessage message = Fixture.getProtocolMessage(); String expectedOne = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1; String expectedTwo = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_2; CallOperation operation = findLoadOperation( message, expectedOne ); JsonArray files = operation.getParameters().get( "files" ).asArray(); assertEquals( expectedOne, files.get( 0 ).asString() ); assertEquals( expectedTwo, files.get( 1 ).asString() ); } @Test public void testLoadMultipleModulesInSameRequest() { ensureFiles( new String[]{ JS_FILE_1 }, false ); ensureFiles( new String[]{ JS_FILE_2 }, true ); Fixture.executeLifeCycleFromServerThread(); TestMessage message = Fixture.getProtocolMessage(); String expectedOne = "rwt-resources/" + getRegistryPath( false ) + "/" + JS_FILE_1; String expectedTwo = "rwt-resources/" + getRegistryPath( true ) + "/" + JS_FILE_2; CallOperation operationOne = findLoadOperation( message, expectedOne ); CallOperation operationTwo = findLoadOperation( message, expectedTwo ); List<Operation> operations = message.getOperations(); assertTrue( operations.indexOf( operationOne ) < operations.indexOf( operationTwo ) ); } @Test public void testLoadMultipleModulesInMultipleRequest() { ensureFiles( new String[]{ JS_FILE_1 }, false ); Fixture.executeLifeCycleFromServerThread(); Fixture.fakeNewRequest(); ensureFiles( new String[]{ JS_FILE_2 }, true ); Fixture.executeLifeCycleFromServerThread(); TestMessage message = Fixture.getProtocolMessage(); String notExpected = "rwt-resources/" + getRegistryPath( false ) + "/" + JS_FILE_1; String expected = "rwt-resources/" + getRegistryPath( true ) + "/" + JS_FILE_2; assertNotNull( findLoadOperation( message, expected ) ); assertNull( findLoadOperation( message, notExpected ) ); } @Test public void testFileNamesChangeAtRuntime() { ensureFiles( new String[]{ JS_FILE_1 } ); Fixture.executeLifeCycleFromServerThread(); newSession(); ensureFiles( new String[]{ JS_FILE_2 } ); Fixture.executeLifeCycleFromServerThread(); TestMessage message = Fixture.getProtocolMessage(); String expected = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1; assertNotNull( findLoadOperation( message, expected ) ); } private void ensureFiles( String[] files ) { ensureFiles( files, false ); } private void ensureFiles( String[] files, boolean secondModule ) { if( secondModule ) { DummyModuleTwo.files = files; loader.ensureModule( DummyModuleTwo.class ); } else { DummyModule.files = files; loader.ensureModule( DummyModule.class ); } } private String getRegistryPath() { return getRegistryPath( false ); } private String getRegistryPath( boolean secondModule ) { String result; if( secondModule ) { result = "DummyModuleTwo" + String.valueOf( DummyModuleTwo.class.hashCode() ); } else { result = "DummyModule" + String.valueOf( DummyModule.class.hashCode() ); } return result; } private CallOperation findLoadOperation( TestMessage message, String file ) { CallOperation[] operations = findLoadOperations( message, file ); return operations.length == 0 ? null : operations[ 0 ]; } private CallOperation[] findLoadOperations( TestMessage message, String file ) { List<CallOperation> result = new ArrayList<CallOperation>(); for( int i = 0; i < message.getOperationCount(); i++ ) { if( message.getOperation( i ) instanceof CallOperation ) { CallOperation operation = ( CallOperation )message.getOperation( i ); if( operation.getTarget().equals( "rwt.client.JavaScriptLoader" ) && "load".equals( operation.getMethodName() ) ) { JsonArray files = operation.getParameters().get( "files" ).asArray(); for( int j = 0; j < files.size(); j++ ) { if( files.get( j ).asString().equals( file ) ) { result.add( operation ); } } } } } return result.toArray( new CallOperation[ 0 ] ); } private void newSession() { ContextProvider.disposeContext(); Fixture.createServiceContext(); Fixture.fakeClient( new WebClient() ); display = new Display(); Fixture.fakeNewRequest(); resourceManager = RWT.getResourceManager(); } static public class DummyModule implements JavaScriptModule { public static String[] files; public String getDirectory() { return "org/eclipse/rap/rwt/internal/resources"; } public String[] getFileNames() { return files; } public ClassLoader getLoader() { return this.getClass().getClassLoader(); } } static public class DummyModuleTwo implements JavaScriptModule { public static String[] files; public String getDirectory() { return "org/eclipse/rap/rwt/internal/resources"; } public String[] getFileNames() { return files; } public ClassLoader getLoader() { return this.getClass().getClassLoader(); } } }