package ro.isdc.wro.manager.runnable;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.mockito.MockitoAnnotations.initMocks;

import java.io.ByteArrayInputStream;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;

import ro.isdc.wro.WroRuntimeException;
import ro.isdc.wro.config.Context;
import ro.isdc.wro.manager.factory.BaseWroManagerFactory;
import ro.isdc.wro.manager.factory.WroManagerFactory;
import ro.isdc.wro.model.WroModel;
import ro.isdc.wro.model.factory.WroModelFactory;
import ro.isdc.wro.model.group.Group;
import ro.isdc.wro.model.group.processor.Injector;
import ro.isdc.wro.model.group.processor.InjectorBuilder;
import ro.isdc.wro.model.resource.Resource;
import ro.isdc.wro.model.resource.locator.UriLocator;
import ro.isdc.wro.model.resource.locator.factory.AbstractUriLocatorFactory;
import ro.isdc.wro.model.resource.locator.factory.UriLocatorFactory;
import ro.isdc.wro.util.WroTestUtils;


/**
 * @author Alex Objelean
 */
public class TestResourceWatcherRunnable {
  private static final String RESOURCE_URI = "/test.js";
  private static final String GROUP_NAME = "g1";
  private ResourceWatcherRunnable victim;
  @Mock
  private UriLocator mockLocator;
  
  @Before
  public void setUp() {
    initMocks(this);
    Context.set(Context.standaloneContext());
    
    mockLocator = Mockito.spy(WroTestUtils.createResourceMockingLocator());
    victim = new ResourceWatcherRunnable(createInjector());
  }

  public Injector createInjector() {
    final UriLocatorFactory locatorFactory = new AbstractUriLocatorFactory() {
      public UriLocator getInstance(String uri) {
        return mockLocator;
      }
    };
    
    final WroModel model = new WroModel().addGroup(new Group(GROUP_NAME).addResource(Resource.create(RESOURCE_URI)));
    final WroModelFactory modelFactory = WroTestUtils.simpleModelFactory(model);
    final WroManagerFactory factory = new BaseWroManagerFactory().setModelFactory(modelFactory).setUriLocatorFactory(
        locatorFactory);
    final Injector injector = InjectorBuilder.create(factory).build();
    return injector;
  }
  
  @Test(expected = NullPointerException.class)
  public void cannotAcceptNullArgument() {
    new ResourceWatcherRunnable(null);
  }
  
  @Test(expected = WroRuntimeException.class)
  public void cannotCreateRunnableWhenRunningOutsideOfContext() {
    Context.unset();
    victim = new ResourceWatcherRunnable(WroTestUtils.createInjector());
  }
  
  @Test
  public void shouldPopulatePreviousHashesAfterFirstRun() {
    victim.run();
    assertTrue(victim.getCurrentHashes().keySet().isEmpty());
    assertEquals(1, victim.getPreviousHashes().keySet().size());
  }
  
  @Test
  public void shouldDetectResourceChange() throws Exception {
    victim = new ResourceWatcherRunnable(createInjector()) {
      @Override
      void onResourceChanged(final Group group, final Resource resource) {
        super.onResourceChanged(group, resource);
        Assert.assertEquals(GROUP_NAME, group.getName());
        Assert.assertEquals(RESOURCE_URI, resource.getUri());
      }
    };
    victim.run();
    assertEquals(1, victim.getPreviousHashes().keySet().size());
    
    Mockito.when(mockLocator.locate(Mockito.anyString())).thenReturn(
        new ByteArrayInputStream("different".getBytes()));

    victim.run();
    assertEquals(1, victim.getPreviousHashes().keySet().size());
  }
}

@@ -225,16 +225,44 @@
 tStream;
+%0Aimport java.io.IOException;
 %0A%0Aimport
@@ -1760,16 +1760,22 @@
 nstance(
+final 
 String u
@@ -2908,16 +2908,247 @@
 ption %7B%0A
+    // flag used to assert that the expected code was invoked%0A    final ThreadLocal%3CBoolean%3E flag = new ThreadLocal%3CBoolean%3E() %7B%0A      @Override%0A      protected Boolean initialValue() %7B%0A        return Boolean.FALSE;%0A      %7D%0A    %7D;%0A
     vict
@@ -3457,24 +3457,56 @@
 .getUri());%0A
+        flag.set(Boolean.TRUE);%0A
       %7D%0A    
@@ -3811,12 +3811,708 @@
 e());%0A  
-%7D
+  assertTrue(flag.get());%0A  %7D%0A%0A  @Test%0A  public void shouldAssumeResourceNotChangedWhenStreamIsUnavailable()%0A      throws Exception %7B%0A    victim = new ResourceWatcherRunnable(createInjector()) %7B%0A      @Override%0A      void onResourceChanged(final Group group, final Resource resource) %7B%0A        super.onResourceChanged(group, resource);%0A        Assert.fail(%22Should not detect the change%22);%0A      %7D%0A    %7D;%0A    victim.run();%0A    assertEquals(1, victim.getPreviousHashes().keySet().size());%0A    %0A    Mockito.when(mockLocator.locate(Mockito.anyString())).thenThrow(new IOException(%22Resource is unavailable%22));%0A    %0A    victim.run();%0A    assertEquals(1, victim.getPreviousHashes().keySet().size());%0A  %7D%0A
 %0A%7D%0A

update unit test