/*******************************************************************************
* Copyright (c) 2012, 2014 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.remote;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import org.eclipse.rap.json.JsonArray;
import org.eclipse.rap.json.JsonObject;
import org.eclipse.rap.rwt.internal.lifecycle.PhaseId;
import org.eclipse.rap.rwt.internal.protocol.ClientMessage;
import org.eclipse.rap.rwt.internal.service.ContextProvider;
import org.eclipse.rap.rwt.remote.OperationHandler;
import org.eclipse.rap.rwt.testfixture.internal.Fixture;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class RemoteObjectLifeCycleAdapter_Test {
@Before
public void setUp() {
Fixture.setUp();
}
@After
public void tearDown() {
Fixture.tearDown();
}
@Test
public void testRender_delegatesToRegisteredRemoteObjects() {
DeferredRemoteObject remoteObject = mockAndRegisterDeferredRemoteObject( "id", null );
RemoteObjectLifeCycleAdapter.render();
verify( remoteObject ).render( same( ContextProvider.getProtocolWriter() ) );
}
@Test
public void testRender_removesAllDestroyedRemoteObjectsFromRegistry() {
setDestroyed( mockAndRegisterDeferredRemoteObject( "deferred", null ) );
setDestroyed( mockAndRegisterLifeCycleRemoteObject( "lifecycle", null ) );
RemoteObjectLifeCycleAdapter.render();
assertNull( RemoteObjectRegistry.getInstance().get( "deferred" ) );
assertNull( RemoteObjectRegistry.getInstance().get( "lifecycle" ) );
}
@Test
public void testRender_doesNotRemoveAliveRemoteObjectsFromRegistry() {
mockAndRegisterDeferredRemoteObject( "deferred", null );
mockAndRegisterLifeCycleRemoteObject( "lifecycle", null );
RemoteObjectLifeCycleAdapter.render();
assertNotNull( RemoteObjectRegistry.getInstance().get( "deferred" ) );
assertNotNull( RemoteObjectRegistry.getInstance().get( "lifecycle" ) );
}
@Test
public void testReadData_delegatesSetOperationsToHandlers() {
OperationHandler handler = mock( OperationHandler.class );
mockAndRegisterDeferredRemoteObject( "id", handler );
JsonObject properties = new JsonObject().add( "foo", "bar" );
ClientMessage message = createMessage( createSetOperation( "id", properties ) );
RemoteObjectLifeCycleAdapter.readData( message );
verify( handler ).handleSet( eq( properties ) );
}
@Test
public void testReadData_delegatesCallOperationsToHandlers() {
OperationHandler handler = mock( OperationHandler.class );
mockAndRegisterDeferredRemoteObject( "id", handler );
JsonObject properties = new JsonObject().add( "foo", "bar" );
ClientMessage message = createMessage( createCallOperation( "id", "method", properties ) );
RemoteObjectLifeCycleAdapter.readData( message );
verify( handler ).handleCall( eq( "method" ), eq( properties ) );
}
@Test
public void testReadData_doesNotDirectlyDelegateNotifyOperationsToHandlers() {
OperationHandler handler = mock( OperationHandler.class );
mockAndRegisterDeferredRemoteObject( "id", handler );
JsonObject properties = new JsonObject().add( "foo", "bar" );
ClientMessage message = createMessage( createNotifyOperation( "id", "event", properties ) );
RemoteObjectLifeCycleAdapter.readData( message );
verifyZeroInteractions( handler );
}
@Test
public void testReadData_schedulesNotifyOperationsForHandlers() {
OperationHandler handler = mock( OperationHandler.class );
mockAndRegisterDeferredRemoteObject( "id", handler );
JsonObject properties = new JsonObject().add( "foo", "bar" );
ClientMessage message = createMessage( createNotifyOperation( "id", "event", properties ) );
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
RemoteObjectLifeCycleAdapter.readData( message );
verify( handler ).handleNotify( eq( "event" ), eq( properties ) );
}
@Test
public void testReadData_doesNotFailWhenNoHandlerRegistered() {
mockAndRegisterDeferredRemoteObject( "id", null );
ClientMessage message = createMessage();
RemoteObjectLifeCycleAdapter.readData( message );
}
@Test
public void testReadData_failsWhenNoHandlerRegisteredForOperations() {
mockAndRegisterDeferredRemoteObject( "id", null );
JsonObject properties = new JsonObject().add( "foo", "bar" );
ClientMessage message = createMessage( createCallOperation( "id", "method", properties ) );
try {
RemoteObjectLifeCycleAdapter.readData( message );
fail();
} catch( UnsupportedOperationException exception ) {
String expected = "No operation handler registered for remote object: id";
assertEquals( expected, exception.getMessage() );
}
}
@Test
public void testReadData_delegatesOnlyToDeferredRemoteObjects() {
OperationHandler deferredHandler = mock( OperationHandler.class );
OperationHandler lifecycleHandler = mock( OperationHandler.class );
mockAndRegisterDeferredRemoteObject( "deferred", deferredHandler );
mockAndRegisterLifeCycleRemoteObject( "lifecycle", lifecycleHandler );
ClientMessage message = createMessage(
createCallOperation( "deferred", "method", new JsonObject().add( "foo", "bar" ) ),
createCallOperation( "lifecycle", "method", new JsonObject().add( "foo", "bar" ) ) );
RemoteObjectLifeCycleAdapter.readData( message );
verify( deferredHandler ).handleCall( eq( "method" ), any( JsonObject.class ) );
verify( lifecycleHandler, never() ).handleCall( eq( "method" ), any( JsonObject.class ) );
}
private static DeferredRemoteObject mockAndRegisterDeferredRemoteObject( String id,
OperationHandler handler )
{
DeferredRemoteObject remoteObject = mock( DeferredRemoteObject.class );
when( remoteObject.getId() ).thenReturn( id );
when( remoteObject.getHandler() ).thenReturn( handler );
RemoteObjectRegistry.getInstance().register( remoteObject );
return remoteObject;
}
private static LifeCycleRemoteObject mockAndRegisterLifeCycleRemoteObject( String id,
OperationHandler handler )
{
LifeCycleRemoteObject remoteObject = mock( LifeCycleRemoteObject.class );
when( remoteObject.getId() ).thenReturn( id );
when( remoteObject.getHandler() ).thenReturn( handler );
RemoteObjectRegistry.getInstance().register( remoteObject );
return remoteObject;
}
private static void setDestroyed( RemoteObjectImpl remoteObject ) {
when( Boolean.valueOf( remoteObject.isDestroyed() ) ).thenReturn( Boolean.TRUE );
}
// TODO [rst] Extract these methods to a utility, merge with Message, Operation?
private static ClientMessage createMessage( JsonArray... operations ) {
JsonArray operationsArray = new JsonArray();
for( JsonArray operation : operations ) {
operationsArray.add( operation );
}
return new ClientMessage( new JsonObject()
.add( "head", new JsonObject() )
.add( "operations", operationsArray ) );
}
private static JsonArray createSetOperation( String target, JsonObject properties ) {
return new JsonArray().add( "set" ).add( target ).add( properties );
}
private static JsonArray createCallOperation( String target, String method, JsonObject properties )
{
return new JsonArray().add( "call" ).add( target ).add( method ).add( properties );
}
private static JsonArray createNotifyOperation( String target, String event, JsonObject properties )
{
return new JsonArray().add( "notify" ).add( target ).add( event ).add( properties );
}
}