/*
 * #%L
 * ACS AEM Commons Bundle
 * %%
 * Copyright (C) 2017 Adobe
 * %%
 * 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.
 * #L%
 */
package com.adobe.acs.commons.wcm.impl;

import com.adobe.granite.ui.clientlibs.ClientLibrary;
import com.adobe.granite.ui.clientlibs.HtmlLibraryManager;
import com.adobe.granite.ui.clientlibs.LibraryType;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.ResourceResolver;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.skyscreamer.jsonassert.JSONAssert;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class DynamicClassicUiClientLibraryServletTest {

    @InjectMocks
    private DynamicClassicUiClientLibraryServlet servlet = new DynamicClassicUiClientLibraryServlet();

    private static final Category LIMIT = new Category("acs-commons.cq-widgets.add-ons.classicui-limit-parsys", "/etc/clientlibs/limit");
    private static final Category PLACEHOLDER = new Category("acs-commons.cq-widgets.add-ons.classicui-parsys-placeholder", "/etc/clientlibs/placeholder");
    private static final Category CUSTOM = new Category("custom", "/etc/clientlibs/custom");

    @Mock
    private SlingHttpServletRequest request;

    @Mock
    private ResourceResolver resourceResolver;

    @Mock
    private SlingHttpServletResponse response;

    @Mock
    private HtmlLibraryManager htmlLibraryManager;

    private StringWriter writer;

    @Before
    public void setup() throws Exception {
        writer = new StringWriter();
        when(response.getWriter()).thenReturn(new PrintWriter(writer));
        when(request.getResourceResolver()).thenReturn(resourceResolver);
        when(resourceResolver.map(anyString())).then(i -> i.getArgumentAt(0, String.class));

        when(htmlLibraryManager.getLibraries(any(String[].class), any(LibraryType.class), eq(true), eq(true))).thenAnswer(i -> {
            Set<ClientLibrary> result = new HashSet<>();
            for (String category : i.getArgumentAt(0, String[].class)) {
                if (category.equals(LIMIT.id)) {
                    result.add(LIMIT.getClientLibrary());
                } else if (category.equals(PLACEHOLDER.id)) {
                    result.add(PLACEHOLDER.getClientLibrary());
                } else if (category.equals(CUSTOM.id)) {
                    result.add(CUSTOM.getClientLibrary());
                }
            }
            return result;
        });

        when(htmlLibraryManager.isMinifyEnabled()).thenReturn(false);
    }

    @Test
    public void testExcludeAll() throws Exception {
        Map<String, Object> config = Collections.singletonMap("exclude.all", true);
        servlet.activate(config);

        servlet.doGet(request, response);
        JSONAssert.assertEquals("{'js':[], 'css':[]}", writer.toString(), false);
    }

    @Test
    public void testDefault() throws Exception {
        servlet.activate(Collections.emptyMap());

        servlet.doGet(request, response);
        JSONAssert.assertEquals("{'js':['/etc/clientlibs/limit.js','/etc/clientlibs/placeholder.js'], 'css':['/etc/clientlibs/limit.css','/etc/clientlibs/placeholder.css']}", writer.toString(), false);
    }

    @Test
    public void testCustom() throws Exception {
        servlet.activate(Collections.singletonMap("categories", new String[] { CUSTOM.id }));

        servlet.doGet(request, response);
        JSONAssert.assertEquals("{'js':['/etc/clientlibs/custom.js'], 'css':['/etc/clientlibs/custom.css']}", writer.toString(), false);
    }

    private static class Category {
        private String id;
        private String path;

        private Category(String id, String path) {
            this.id = id;
            this.path = path;
        }

        private ClientLibrary getClientLibrary() {
            ClientLibrary cl = mock(ClientLibrary.class);
            when(cl.getIncludePath(any(LibraryType.class), anyBoolean())).then(i -> {
                return path + (i.getArgumentAt(1, Boolean.class) ? ".min" : "") + i.getArgumentAt(0, LibraryType.class).extension;
            });
            return cl;
        }
    }

}
@@ -842,16 +842,56 @@
 ryType;%0A
+import com.day.cq.commons.Externalizer;%0A
 import o
@@ -2105,16 +2105,125 @@
 ustom%22);
+%0A    private static final Category CUSTOM_CONTEXT = new Category(%22custom-context%22, %22/etc/clientlibs/custom%22);
 %0A%0A    @M
@@ -2446,24 +2446,74 @@
 ryManager;%0A%0A
+    @Mock%0A    private Externalizer externalizer;%0A%0A
     private 
@@ -2772,16 +2772,16 @@
 olver);%0A
-
         
@@ -2862,24 +2862,165 @@
 g.class));%0A%0A
+        when(externalizer.relativeLink(any(SlingHttpServletRequest.class), anyString())).thenAnswer(i -%3E i.getArgumentAt(1, String.class));%0A%0A
         when

Update unit-test #1187