package replicant;

import elemental2.dom.Window;
import elemental2.webstorage.Storage;
import elemental2.webstorage.WebStorageWindow;
import java.lang.reflect.Field;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.realityforge.guiceyloops.shared.ValueUtil;
import org.testng.annotations.Test;
import static org.mockito.Mockito.*;
import static org.testng.Assert.*;

public class WebStorageCacheServiceTest
  extends AbstractReplicantTest
{
  @Test
  public void install_defaults()
  {
    final WebStorageWindow window = new WebStorageWindow();
    final Storage storage = mock( Storage.class );
    window.localStorage = storage;
    setWindow( window );

    assertNull( Replicant.context().getCacheService() );

    WebStorageCacheService.install();

    final CacheService cacheService = Replicant.context().getCacheService();
    assertNotNull( cacheService );
    assertTrue( cacheService instanceof WebStorageCacheService );
    assertEquals( ( (WebStorageCacheService) cacheService ).getStorage(), storage );
  }

  @Test
  public void install_withSpecificStorage()
  {
    assertNull( Replicant.context().getCacheService() );

    final Storage storage = mock( Storage.class );

    WebStorageCacheService.install( storage );

    final CacheService cacheService = Replicant.context().getCacheService();
    assertNotNull( cacheService );
    assertTrue( cacheService instanceof WebStorageCacheService );
    assertEquals( ( (WebStorageCacheService) cacheService ).getStorage(), storage );
  }

  @Test
  public void install_withSpecificWindow()
  {
    final WebStorageWindow window = new WebStorageWindow();
    final Storage storage = mock( Storage.class );
    window.localStorage = storage;

    assertNull( Replicant.context().getCacheService() );

    WebStorageCacheService.install( window );

    final CacheService cacheService = Replicant.context().getCacheService();
    assertNotNull( cacheService );
    assertTrue( cacheService instanceof WebStorageCacheService );
    assertEquals( ( (WebStorageCacheService) cacheService ).getStorage(), storage );
  }

  @Test
  public void invalidate_whenNotPresent()
  {
    final Storage storage = mock( Storage.class );

    final WebStorageCacheService service = new WebStorageCacheService( storage );

    final ChannelAddress address = newAddress();

    when( storage.getItem( WebStorageCacheService.ETAG_INDEX + '-' + address.getSystemId() ) ).thenReturn( null );

    assertFalse( service.invalidate( address ) );

    verify( storage ).getItem( WebStorageCacheService.ETAG_INDEX + '-' + address.getSystemId() );
  }

  @Nonnull
  private ChannelAddress newAddress()
  {
    return new ChannelAddress( ValueUtil.randomInt(), ValueUtil.randomInt() );
  }

  private void setWindow( @Nullable final Window window )
  {
    try
    {
      final Class<?> type = Class.forName( "elemental2.dom.DomGlobal__Constants" );
      final Field field = type.getDeclaredField( "window" );
      field.setAccessible( true );
      field.set( null, window );
    }
    catch ( final ClassNotFoundException | NoSuchFieldException | IllegalAccessException e )
    {
      throw new IllegalStateException( "Error setting field", e );
    }
  }
}

@@ -35,22 +35,25 @@
 al2.dom.
-Window
+DomGlobal
 ;%0Aimport
@@ -146,94 +146,28 @@
 java
-.lang.reflect.Field;%0Aimport javax.annotation.Nonnull;%0Aimport javax.annotation.Nullable
+x.annotation.Nonnull
 ;%0Aim
@@ -600,27 +600,33 @@
     
-setW
+DomGlobal.w
 indow
-(
+ =
  window
- )
 ;%0A%0A 
@@ -2694,479 +2694,7 @@
 %0A  %7D
-%0A%0A  private void setWindow( @Nullable final Window window )%0A  %7B%0A    try%0A    %7B%0A      final Class%3C?%3E type = Class.forName( %22elemental2.dom.DomGlobal__Constants%22 );%0A      final Field field = type.getDeclaredField( %22window%22 );%0A      field.setAccessible( true );%0A      field.set( null, window );%0A    %7D%0A    catch ( final ClassNotFoundException %7C NoSuchFieldException %7C IllegalAccessException e )%0A    %7B%0A      throw new IllegalStateException( %22Error setting field%22, e );%0A    %7D%0A  %7D
 %0A%7D%0A

Upgrade to the latest Elemental2 APIs