/* * Copyright 2017 ThoughtWorks, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.thoughtworks.go.server.service; import com.google.gson.annotations.SerializedName; import com.thoughtworks.go.util.*; import org.apache.commons.io.FileUtils; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.mockito.Matchers; import javax.servlet.ServletContext; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.UUID; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class RailsAssetsServiceTest { RailsAssetsService railsAssetsService; private File assetsDir; private ServletContext context; private SystemEnvironment systemEnvironment; @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); @Before public void setup() throws IOException { context = mock(ServletContext.class); systemEnvironment = mock(SystemEnvironment.class); when(systemEnvironment.useCompressedJs()).thenReturn(true); railsAssetsService = new RailsAssetsService(systemEnvironment); railsAssetsService.setServletContext(context); assetsDir = tempFolder.newFolder("assets-" + UUID.randomUUID().toString()); } @After public void teardown() { FileUtils.deleteQuietly(assetsDir); } @Test public void shouldNotInitializeAssetManifestWhenUsingRails4InDevelopmentMode() throws IOException { when(systemEnvironment.useCompressedJs()).thenReturn(false); railsAssetsService = new RailsAssetsService(systemEnvironment); railsAssetsService.setServletContext(context); railsAssetsService.initialize(); assertThat(railsAssetsService.getRailsAssetsManifest(), is(nullValue())); } @Test public void shouldGetAssetPathFromManifestJson() throws IOException { FileUtil.writeContentToFile(json, new File(assetsDir, ".sprockets-manifest-digest.json")); when(context.getInitParameter("rails.root")).thenReturn(""); when(context.getRealPath(Matchers.<String>any())).thenReturn(assetsDir.getAbsolutePath()); railsAssetsService.initialize(); assertThat(railsAssetsService.getAssetPath("application.js"), is("assets/application-bfdbd4fff63b0cd45c50ce7a79fe0f53.js")); assertThat(railsAssetsService.getAssetPath("junk.js"), is(nullValue())); } @Test public void shouldThrowExceptionIfManifestFileIsNotFoundInAssetsDir() throws IOException { when(context.getInitParameter("rails.root")).thenReturn(""); when(context.getRealPath(Matchers.<String>any())).thenReturn(assetsDir.getAbsolutePath()); try { railsAssetsService.initialize(); fail("Expected exception to be thrown"); } catch (Exception e) { assertThat(e.getMessage(), is("Manifest json file was not found at " + assetsDir.getAbsolutePath())); } } @Test public void shouldThrowExceptionIfAssetsDirDoesNotExist() throws IOException { when(context.getInitParameter("rails.root")).thenReturn(""); when(context.getRealPath(Matchers.<String>any())).thenReturn("DoesNotExist"); try { railsAssetsService.initialize(); fail("Expected exception to be thrown"); } catch (Exception e) { assertThat(e.getMessage(), is("Assets directory does not exist DoesNotExist")); } } @Test public void shouldNotIncludeDigestPathInDevelopmentEnvironment() throws IOException { when(systemEnvironment.useCompressedJs()).thenReturn(false); railsAssetsService.initialize(); assertThat(railsAssetsService.getAssetPath("junk.js"), is("assets/junk.js")); } @Test public void shouldHaveAssetsAsTheSerializedNameForAssetsMapInRailsAssetsManifest_ThisIsRequiredSinceManifestFileGeneratedBySprocketsHasAMapOfAssetsWhichThisServiceNeedsAccessTo(){ List<Field> fields = ArrayUtil.asList(RailsAssetsService.RailsAssetsManifest.class.getDeclaredFields()); ArrayList<Field> fieldsAnnotatedWithSerializedNameAsAssets = new ArrayList<>(); ListUtil.filterInto(fieldsAnnotatedWithSerializedNameAsAssets, fields, new Filter<Field>() { @Override public boolean matches(Field field) { if (field.isAnnotationPresent(SerializedName.class)) { SerializedName annotation = field.getAnnotation(SerializedName.class); if (annotation.value().equals("assets")) { return true; } return false; } return false; } }); assertThat("Expected a field annotated with SerializedName 'assets'", fieldsAnnotatedWithSerializedNameAsAssets.isEmpty(), is(false)); assertThat(fieldsAnnotatedWithSerializedNameAsAssets.size(), is(1)); assertThat(fieldsAnnotatedWithSerializedNameAsAssets.get(0).getType().getCanonicalName(), is(HashMap.class.getCanonicalName())); } private String json = "{\n" + " \"files\": {\n" + " \"application-bfdbd4fff63b0cd45c50ce7a79fe0f53.js\": {\n" + " \"logical_path\": \"application.js\",\n" + " \"mtime\": \"2014-08-26T12:39:43+05:30\",\n" + " \"size\": 1091366,\n" + " \"digest\": \"bfdbd4fff63b0cd45c50ce7a79fe0f53\"\n" + " },\n" + " \"application-4b25c82f986c0bef78151a4ab277c3e4.css\": {\n" + " \"logical_path\": \"application.css\",\n" + " \"mtime\": \"2014-08-26T13:45:30+05:30\",\n" + " \"size\": 513,\n" + " \"digest\": \"4b25c82f986c0bef78151a4ab277c3e4\"\n" + " }\n" + " },\n" + " \"assets\": {\n" + " \"application.js\": \"application-bfdbd4fff63b0cd45c50ce7a79fe0f53.js\",\n" + " \"application.css\": \"application-4b25c82f986c0bef78151a4ab277c3e4.css\"\n" + " }\n" + "}"; }