| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,193 @@ | ||
| /* | ||
| * See the NOTICE file distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This is free software; you can redistribute it and/or modify it | ||
| * under the terms of the GNU Lesser General Public License as | ||
| * published by the Free Software Foundation; either version 2.1 of | ||
| * the License, or (at your option) any later version. | ||
| * | ||
| * This software is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| * Lesser General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Lesser General Public | ||
| * License along with this software; if not, write to the Free | ||
| * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
| * 02110-1301 USA, or see the FSF site: http://www.fsf.org. | ||
| */ | ||
| package org.xwiki.icon.macro.internal; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Set; | ||
|
|
||
| import javax.inject.Inject; | ||
| import javax.inject.Named; | ||
| import javax.inject.Singleton; | ||
|
|
||
| import org.xwiki.bridge.DocumentModelBridge; | ||
| import org.xwiki.bridge.internal.DocumentContextExecutor; | ||
| import org.xwiki.component.annotation.Component; | ||
| import org.xwiki.icon.IconException; | ||
| import org.xwiki.icon.IconRenderer; | ||
| import org.xwiki.icon.IconSet; | ||
| import org.xwiki.icon.IconSetManager; | ||
| import org.xwiki.icon.macro.DisplayIconMacroParameters; | ||
| import org.xwiki.model.reference.DocumentReference; | ||
| import org.xwiki.model.reference.EntityReferenceSerializer; | ||
| import org.xwiki.rendering.async.internal.AbstractExecutedContentMacro; | ||
| import org.xwiki.rendering.async.internal.block.BlockAsyncRendererConfiguration; | ||
| import org.xwiki.rendering.block.Block; | ||
| import org.xwiki.rendering.block.XDOM; | ||
| import org.xwiki.rendering.listener.MetaData; | ||
| import org.xwiki.rendering.macro.MacroExecutionException; | ||
| import org.xwiki.rendering.syntax.Syntax; | ||
| import org.xwiki.rendering.transformation.MacroTransformationContext; | ||
| import org.xwiki.security.authorization.ContextualAuthorizationManager; | ||
| import org.xwiki.security.authorization.Right; | ||
| import org.xwiki.user.UserReferenceSerializer; | ||
|
|
||
| /** | ||
| * Macro for displaying an icon. | ||
| * | ||
| * @version $Id$ | ||
| * @since 14.10.6 | ||
| * @since 15.2RC1 | ||
| */ | ||
| @Component | ||
| @Named("displayIcon") | ||
| @Singleton | ||
| public class DisplayIconMacro extends AbstractExecutedContentMacro<DisplayIconMacroParameters> | ||
| { | ||
| private static final String DESCRIPTION = "Display an icon."; | ||
|
|
||
| @Inject | ||
| private IconSetManager iconSetManager; | ||
|
|
||
| @Inject | ||
| private IconRenderer iconRenderer; | ||
|
|
||
| @Inject | ||
| private EntityReferenceSerializer<String> defaultEntityReferenceSerializer; | ||
|
|
||
| @Inject | ||
| private ContextualAuthorizationManager contextualAuthorization; | ||
|
|
||
| @Inject | ||
| @Named("document") | ||
| private UserReferenceSerializer<DocumentReference> documentUserSerializer; | ||
|
|
||
| @Inject | ||
| private DocumentContextExecutor documentContextExecutor; | ||
|
|
||
| /** | ||
| * Default constructor. | ||
| */ | ||
| public DisplayIconMacro() | ||
| { | ||
| super("Icon", DESCRIPTION, null, DisplayIconMacroParameters.class); | ||
|
|
||
| setDefaultCategories(Set.of(DEFAULT_CATEGORY_CONTENT)); | ||
| } | ||
|
|
||
| @Override | ||
| public List<Block> execute(DisplayIconMacroParameters parameters, String content, | ||
| MacroTransformationContext context) throws MacroExecutionException | ||
| { | ||
| List<Block> result; | ||
|
|
||
| try { | ||
| IconSet iconSet = getIconSet(parameters); | ||
|
|
||
| if (iconSet == null) { | ||
| result = List.of(); | ||
| } else { | ||
| XDOM iconBlock = parseIcon(parameters, context, iconSet); | ||
|
|
||
| BlockAsyncRendererConfiguration rendererConfiguration = | ||
| createBlockAsyncRendererConfiguration(null, iconBlock, null, context); | ||
| rendererConfiguration.setAsyncAllowed(false); | ||
| rendererConfiguration.setCacheAllowed(false); | ||
|
|
||
| if (iconSet.getSourceDocumentReference() != null) { | ||
| DocumentReference sourceDocumentReference = iconSet.getSourceDocumentReference(); | ||
|
|
||
| DocumentModelBridge sourceDocument = | ||
| this.documentAccessBridge.getDocumentInstance(sourceDocumentReference); | ||
| DocumentReference authorReference = | ||
| this.documentUserSerializer.serialize(sourceDocument.getAuthors().getContentAuthor()); | ||
|
|
||
| rendererConfiguration.setSecureReference(sourceDocumentReference, authorReference); | ||
| rendererConfiguration.useEntity(sourceDocumentReference); | ||
|
|
||
| String stringDocumentReference = | ||
| this.defaultEntityReferenceSerializer.serialize(iconSet.getSourceDocumentReference()); | ||
| rendererConfiguration.setTransformationId(stringDocumentReference); | ||
| rendererConfiguration.setResricted(false); | ||
|
|
||
| result = this.documentContextExecutor.call( | ||
| () -> List.of(this.executor.execute(rendererConfiguration)), | ||
| sourceDocument | ||
| ); | ||
| } else { | ||
| result = List.of(this.executor.execute(rendererConfiguration)); | ||
| } | ||
| } | ||
| } catch (MacroExecutionException e) { | ||
| throw e; | ||
| } catch (Exception e) { | ||
| throw new MacroExecutionException("Failed parsing and executing the icon.", e); | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| private XDOM parseIcon(DisplayIconMacroParameters parameters, MacroTransformationContext context, IconSet iconSet) | ||
| throws IconException, MacroExecutionException | ||
| { | ||
| String iconContent = this.iconRenderer.render(parameters.getName(), iconSet); | ||
| MetaData metaData = null; | ||
|
|
||
| if (iconSet.getSourceDocumentReference() != null) { | ||
| String stringReference = | ||
| this.defaultEntityReferenceSerializer.serialize(iconSet.getSourceDocumentReference()); | ||
| metaData = new MetaData(Map.of(MetaData.SOURCE, stringReference)); | ||
| } | ||
|
|
||
| return this.parser.parse(iconContent, Syntax.XWIKI_2_1, context, false, metaData, | ||
| context.isInline()); | ||
| } | ||
|
|
||
| private IconSet getIconSet(DisplayIconMacroParameters parameters) throws IconException, MacroExecutionException | ||
| { | ||
| IconSet iconSet; | ||
|
|
||
| if (parameters.getIconSet() == null) { | ||
| iconSet = this.iconSetManager.getCurrentIconSet(); | ||
| } else { | ||
| iconSet = this.iconSetManager.getIconSet(parameters.getIconSet()); | ||
| } | ||
|
|
||
| // Check if the current user can access the icon theme. If not, fall back to the default icon theme or throw | ||
| // an exception when the fallback is disabled. | ||
| if (iconSet != null && iconSet.getSourceDocumentReference() != null | ||
| && !this.contextualAuthorization.hasAccess(Right.VIEW, iconSet.getSourceDocumentReference())) | ||
| { | ||
| if (parameters.isFallback()) { | ||
| iconSet = null; | ||
| } else { | ||
| throw new MacroExecutionException( | ||
| String.format("Current user [%s] doesn't have view rights on the icon set's document [%s]", | ||
| this.documentAccessBridge.getCurrentUserReference(), iconSet.getSourceDocumentReference())); | ||
| } | ||
| } | ||
|
|
||
| if (parameters.isFallback() && (iconSet == null || !iconSet.hasIcon(parameters.getName()))) { | ||
| iconSet = this.iconSetManager.getDefaultIconSet(); | ||
| } | ||
|
|
||
| return iconSet; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # --------------------------------------------------------------------------- | ||
| # See the NOTICE file distributed with this work for additional | ||
| # information regarding copyright ownership. | ||
| # | ||
| # This is free software; you can redistribute it and/or modify it | ||
| # under the terms of the GNU Lesser General Public License as | ||
| # published by the Free Software Foundation; either version 2.1 of | ||
| # the License, or (at your option) any later version. | ||
| # | ||
| # This software is distributed in the hope that it will be useful, | ||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| # Lesser General Public License for more details. | ||
| # | ||
| # You should have received a copy of the GNU Lesser General Public | ||
| # License along with this software; if not, write to the Free | ||
| # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
| # 02110-1301 USA, or see the FSF site: http://www.fsf.org. | ||
| # --------------------------------------------------------------------------- | ||
| rendering.macro.displayIcon.name=Icon | ||
| rendering.macro.displayIcon.description=Display an icon. | ||
| rendering.macro.displayIcon.parameter.name.name=Name | ||
| rendering.macro.displayIcon.parameter.name.description=The name of the icon. | ||
| rendering.macro.displayIcon.parameter.iconSet.name=Icon Set | ||
| rendering.macro.displayIcon.parameter.iconSet.description=The name of the icon set. | ||
| rendering.macro.displayIcon.parameter.fallback.name=Fallback | ||
| rendering.macro.displayIcon.parameter.fallback.description=If the icon shall be loaded from the default icon set when \ | ||
| the icon or icon set is not available, true by default. | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| org.xwiki.icon.macro.internal.DisplayIconMacro |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| /* | ||
| * See the NOTICE file distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This is free software; you can redistribute it and/or modify it | ||
| * under the terms of the GNU Lesser General Public License as | ||
| * published by the Free Software Foundation; either version 2.1 of | ||
| * the License, or (at your option) any later version. | ||
| * | ||
| * This software is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| * Lesser General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Lesser General Public | ||
| * License along with this software; if not, write to the Free | ||
| * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
| * 02110-1301 USA, or see the FSF site: http://www.fsf.org. | ||
| */ | ||
|
|
||
| package org.xwiki.icon.macro; | ||
|
|
||
| import org.xwiki.bridge.DocumentAccessBridge; | ||
| import org.xwiki.icon.Icon; | ||
| import org.xwiki.icon.IconException; | ||
| import org.xwiki.icon.IconSet; | ||
| import org.xwiki.icon.IconSetCache; | ||
| import org.xwiki.icon.IconSetManager; | ||
| import org.xwiki.model.reference.DocumentReference; | ||
| import org.xwiki.observation.ObservationManager; | ||
| import org.xwiki.rendering.test.integration.junit5.RenderingTests; | ||
| import org.xwiki.script.ScriptContextInitializer; | ||
| import org.xwiki.security.authorization.AuthorizationManager; | ||
| import org.xwiki.security.authorization.ContextualAuthorizationManager; | ||
| import org.xwiki.security.authorization.Right; | ||
| import org.xwiki.skin.SkinManager; | ||
| import org.xwiki.skinx.SkinExtension; | ||
| import org.xwiki.test.annotation.AllComponents; | ||
| import org.xwiki.test.mockito.MockitoComponentManager; | ||
|
|
||
| import com.xpn.xwiki.doc.XWikiDocument; | ||
|
|
||
| import static org.mockito.Mockito.when; | ||
|
|
||
| /** | ||
| * Run all tests found in {@code *.test} files located in the classpath. These {@code *.test} files must follow the | ||
| * conventions described in {@link org.xwiki.rendering.test.integration.TestDataParser}. | ||
| * | ||
| * @version $Id$ | ||
| */ | ||
| @AllComponents | ||
| public class IntegrationTests implements RenderingTests | ||
| { | ||
| private static final DocumentReference ICON_DOCUMENT_REFERENCE = new DocumentReference("xwiki", "Icon", "Document"); | ||
|
|
||
| /** | ||
| * Initializes various mocks to prevent errors in the integration tests. | ||
| * | ||
| * @param componentManager the component manager of the tests | ||
| * @throws Exception when the initialization fails | ||
| */ | ||
| @RenderingTests.Initialized | ||
| public void initialize(MockitoComponentManager componentManager) throws Exception | ||
| { | ||
| // Mock the authorization managers as they try initializing a cache which fails (infinispan is not available | ||
| // in rendering tests). | ||
| ContextualAuthorizationManager authorizationManager = | ||
| componentManager.registerMockComponent(ContextualAuthorizationManager.class); | ||
| // Grant view right on the icon document. | ||
| when(authorizationManager.hasAccess(Right.VIEW, ICON_DOCUMENT_REFERENCE)).thenReturn(true); | ||
| componentManager.registerMockComponent(AuthorizationManager.class); | ||
|
|
||
| // Mock the icon set cache as it fails. | ||
| componentManager.registerMockComponent(IconSetCache.class); | ||
|
|
||
| // Mock skin extensions. | ||
| componentManager.registerMockComponent(SkinExtension.class, "ssx"); | ||
| componentManager.registerMockComponent(SkinExtension.class, "jsx"); | ||
| componentManager.registerMockComponent(SkinExtension.class, "linkx"); | ||
|
|
||
| // Mock various components for the script context initialization. | ||
| componentManager.registerMockComponent(SkinManager.class); | ||
| componentManager.registerMockComponent(ScriptContextInitializer.class, "xwiki"); | ||
| componentManager.registerMockComponent(ObservationManager.class); | ||
|
|
||
| DocumentAccessBridge documentAccessBridge = componentManager.registerMockComponent(DocumentAccessBridge.class); | ||
| XWikiDocument testDocument = new XWikiDocument(ICON_DOCUMENT_REFERENCE); | ||
| when(documentAccessBridge.getDocumentInstance(ICON_DOCUMENT_REFERENCE)).thenReturn(testDocument); | ||
|
|
||
| // Mock the icon set manager as we're not in a real enviornment where icon sets can be loaded. | ||
| IconSetManager iconSetManager = componentManager.registerMockComponent(IconSetManager.class); | ||
| setupIconThemes(iconSetManager); | ||
| } | ||
|
|
||
| private void setupIconThemes(IconSetManager iconSetManager) throws IconException | ||
| { | ||
| // The current icon set, the test icon set. | ||
| IconSet iconSet = new IconSet("test"); | ||
| iconSet.addIcon("home", new Icon("homeIcon")); | ||
| iconSet.addIcon("page", new Icon("pageIcon")); | ||
| iconSet.setRenderWiki("(% class=\"icon\" data-xwiki-icon=\"$icon\" %)i(%%)"); | ||
| when(iconSetManager.getCurrentIconSet()).thenReturn(iconSet); | ||
|
|
||
| // A special icon set to test loading icons from a different icon set. | ||
| IconSet specialSet = new IconSet("special"); | ||
| specialSet.addIcon("home", new Icon("home")); | ||
| specialSet.setRenderWiki("special $icon"); | ||
| when(iconSetManager.getIconSet("special")).thenReturn(specialSet); | ||
|
|
||
| // A document-based icon set to test executing in the context of a document. | ||
| IconSet documentIconSet = new IconSet("document"); | ||
| documentIconSet.addIcon("document", new Icon("executed")); | ||
| documentIconSet.setRenderWiki("document $icon"); | ||
| documentIconSet.setSourceDocumentReference(new DocumentReference(ICON_DOCUMENT_REFERENCE)); | ||
| when(iconSetManager.getIconSet("document")).thenReturn(documentIconSet); | ||
|
|
||
| // The default icon set to test fallback to the default when the current or specified icon set doesn't | ||
| // contain an icon. | ||
| IconSet defaultSet = new IconSet("default"); | ||
| defaultSet.addIcon("fallback", new Icon("fallbackIcon")); | ||
| defaultSet.setRenderWiki("fallback $icon"); | ||
| when(iconSetManager.getDefaultIconSet()).thenReturn(defaultSet); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,200 @@ | ||
| /* | ||
| * See the NOTICE file distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This is free software; you can redistribute it and/or modify it | ||
| * under the terms of the GNU Lesser General Public License as | ||
| * published by the Free Software Foundation; either version 2.1 of | ||
| * the License, or (at your option) any later version. | ||
| * | ||
| * This software is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| * Lesser General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Lesser General Public | ||
| * License along with this software; if not, write to the Free | ||
| * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
| * 02110-1301 USA, or see the FSF site: http://www.fsf.org. | ||
| */ | ||
| package org.xwiki.icon.macro.internal; | ||
|
|
||
| import java.util.List; | ||
| import java.util.concurrent.Callable; | ||
|
|
||
| import javax.inject.Named; | ||
|
|
||
| import org.junit.jupiter.api.BeforeEach; | ||
| import org.junit.jupiter.api.Test; | ||
| import org.xwiki.bridge.DocumentAccessBridge; | ||
| import org.xwiki.bridge.internal.DocumentContextExecutor; | ||
| import org.xwiki.icon.Icon; | ||
| import org.xwiki.icon.IconException; | ||
| import org.xwiki.icon.IconRenderer; | ||
| import org.xwiki.icon.IconSet; | ||
| import org.xwiki.icon.IconSetManager; | ||
| import org.xwiki.icon.macro.DisplayIconMacroParameters; | ||
| import org.xwiki.model.reference.DocumentReference; | ||
| import org.xwiki.model.reference.EntityReferenceSerializer; | ||
| import org.xwiki.rendering.async.internal.block.BlockAsyncRendererConfiguration; | ||
| import org.xwiki.rendering.async.internal.block.BlockAsyncRendererExecutor; | ||
| import org.xwiki.rendering.block.Block; | ||
| import org.xwiki.rendering.block.MetaDataBlock; | ||
| import org.xwiki.rendering.block.WordBlock; | ||
| import org.xwiki.rendering.block.XDOM; | ||
| import org.xwiki.rendering.macro.MacroContentParser; | ||
| import org.xwiki.rendering.macro.MacroExecutionException; | ||
| import org.xwiki.rendering.syntax.Syntax; | ||
| import org.xwiki.rendering.transformation.MacroTransformationContext; | ||
| import org.xwiki.security.authorization.ContextualAuthorizationManager; | ||
| import org.xwiki.security.authorization.Right; | ||
| import org.xwiki.test.junit5.mockito.InjectMockComponents; | ||
| import org.xwiki.test.junit5.mockito.MockComponent; | ||
| import org.xwiki.user.UserReferenceSerializer; | ||
|
|
||
| import com.xpn.xwiki.doc.XWikiDocument; | ||
| import com.xpn.xwiki.test.MockitoOldcore; | ||
| import com.xpn.xwiki.test.junit5.mockito.OldcoreTest; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| import static org.junit.jupiter.api.Assertions.assertSame; | ||
| import static org.junit.jupiter.api.Assertions.assertThrows; | ||
| import static org.mockito.ArgumentMatchers.any; | ||
| import static org.mockito.ArgumentMatchers.anyBoolean; | ||
| import static org.mockito.ArgumentMatchers.anyString; | ||
| import static org.mockito.ArgumentMatchers.eq; | ||
| import static org.mockito.Mockito.mock; | ||
| import static org.mockito.Mockito.verify; | ||
| import static org.mockito.Mockito.verifyNoInteractions; | ||
| import static org.mockito.Mockito.when; | ||
|
|
||
| /** | ||
| * Unit test for {@link DisplayIconMacro}. | ||
| * | ||
| * @version $Id$ | ||
| */ | ||
| @OldcoreTest | ||
| class DisplayIconMacroTest | ||
| { | ||
| private static final DocumentReference ICON_DOCUMENT_REFERENCE = new DocumentReference("xwiki", "Icon", "Document"); | ||
|
|
||
| private static final DocumentReference AUTHOR = new DocumentReference("xwiki", "XWiki", "Author"); | ||
|
|
||
| @MockComponent | ||
| private ContextualAuthorizationManager contextualAuthorizationManager; | ||
|
|
||
| @MockComponent | ||
| private IconSetManager iconSetManager; | ||
|
|
||
| @MockComponent | ||
| private IconRenderer iconRenderer; | ||
|
|
||
| @MockComponent | ||
| private MacroContentParser macroContentParser; | ||
|
|
||
| @MockComponent | ||
| private DocumentContextExecutor documentContextExecutor; | ||
|
|
||
| @MockComponent | ||
| private BlockAsyncRendererExecutor blockAsyncRendererExecutor; | ||
|
|
||
| @MockComponent | ||
| private EntityReferenceSerializer<String> defaultEntityReferenceSerializer; | ||
|
|
||
| @MockComponent | ||
| @Named("document") | ||
| private UserReferenceSerializer<DocumentReference> documentUserSerializer; | ||
|
|
||
| @MockComponent | ||
| private DocumentAccessBridge documentAccessBridge; | ||
|
|
||
| @InjectMockComponents | ||
| private DisplayIconMacro displayIconMacro; | ||
|
|
||
| private final DisplayIconMacroParameters displayIconMacroParameters = new DisplayIconMacroParameters(); | ||
|
|
||
| private XWikiDocument iconDocument; | ||
|
|
||
| @BeforeEach | ||
| public void before(MockitoOldcore oldcore) throws Exception | ||
| { | ||
| this.iconDocument = new XWikiDocument(ICON_DOCUMENT_REFERENCE); | ||
| this.iconDocument.setContentAuthorReference(AUTHOR); | ||
| oldcore.getSpyXWiki().saveDocument(this.iconDocument, oldcore.getXWikiContext()); | ||
|
|
||
| IconSet documentIconSet = new IconSet("document"); | ||
| documentIconSet.addIcon("home", new Icon("homeIcon")); | ||
| documentIconSet.setRenderWiki("icon $icon context {{contextDocumentAuthor /}}"); | ||
| documentIconSet.setSourceDocumentReference(ICON_DOCUMENT_REFERENCE); | ||
| when(this.iconSetManager.getIconSet("document")).thenReturn(documentIconSet); | ||
|
|
||
| this.displayIconMacroParameters.setName("home"); | ||
| this.displayIconMacroParameters.setIconSet("document"); | ||
|
|
||
| when(this.iconRenderer.render(anyString(), any(IconSet.class))) | ||
| .then(invocation -> invocation.getArgument(0, String.class)); | ||
| when(this.macroContentParser.parse(anyString(), eq(Syntax.XWIKI_2_1), any(), eq(false), any(), anyBoolean())) | ||
| .then(invocation -> new XDOM(List.of(new WordBlock(invocation.getArgument(0))))); | ||
| when(this.documentContextExecutor.call(any(), any())) | ||
| .then(invocation -> invocation.getArgument(0, Callable.class).call()); | ||
| when(this.blockAsyncRendererExecutor.execute(any())).then(invocation -> invocation.getArgument(0, | ||
| BlockAsyncRendererConfiguration.class).getBlock()); | ||
| when(this.defaultEntityReferenceSerializer.serialize(ICON_DOCUMENT_REFERENCE)) | ||
| .thenReturn("xwiki:Icon.Document"); | ||
| when(this.documentUserSerializer.serialize(any())).thenReturn(AUTHOR); | ||
| when(this.documentAccessBridge.getDocumentInstance(ICON_DOCUMENT_REFERENCE)).thenReturn(this.iconDocument); | ||
| } | ||
|
|
||
| @Test | ||
| void accessDenied() | ||
| { | ||
| when(this.contextualAuthorizationManager.hasAccess(Right.VIEW, ICON_DOCUMENT_REFERENCE)).thenReturn(false); | ||
| this.displayIconMacroParameters.setFallback(false); | ||
|
|
||
| MacroExecutionException executionException = assertThrows(MacroExecutionException.class, | ||
| () -> this.displayIconMacro.execute(this.displayIconMacroParameters, null, | ||
| mock(MacroTransformationContext.class))); | ||
| assertEquals(String.format("Current user [%s] doesn't have view rights on the icon set's document [%s]", null, | ||
| ICON_DOCUMENT_REFERENCE), executionException.getMessage()); | ||
| } | ||
|
|
||
| @Test | ||
| void fallbackWhenAccessDenied() throws MacroExecutionException, IconException | ||
| { | ||
| when(this.contextualAuthorizationManager.hasAccess(Right.VIEW, ICON_DOCUMENT_REFERENCE)).thenReturn(false); | ||
| IconSet defaultIconSet = mock(IconSet.class); | ||
| when(this.iconSetManager.getDefaultIconSet()).thenReturn(defaultIconSet); | ||
|
|
||
| List<Block> result = | ||
| this.displayIconMacro.execute(this.displayIconMacroParameters, null, new MacroTransformationContext()); | ||
| assertEquals(result, List.of(new MetaDataBlock(List.of(new WordBlock("home"))))); | ||
| verify(this.iconRenderer).render("home", defaultIconSet); | ||
| verifyNoInteractions(this.documentContextExecutor); | ||
| } | ||
|
|
||
| @Test | ||
| void throwsWhenRenderingIconFails() throws IconException | ||
| { | ||
| when(this.contextualAuthorizationManager.hasAccess(Right.VIEW, ICON_DOCUMENT_REFERENCE)).thenReturn(true); | ||
|
|
||
| IconException testException = new IconException("Test"); | ||
| when(this.iconRenderer.render("home", this.iconSetManager.getIconSet("document"))).thenThrow(testException); | ||
|
|
||
| MacroExecutionException result = assertThrows(MacroExecutionException.class, () -> | ||
| this.displayIconMacro.execute(this.displayIconMacroParameters, null, new MacroTransformationContext())); | ||
|
|
||
| assertEquals("Failed parsing and executing the icon.", result.getMessage()); | ||
| assertSame(testException, result.getCause()); | ||
| } | ||
|
|
||
| @Test | ||
| void executesInContext() throws Exception | ||
| { | ||
| when(this.contextualAuthorizationManager.hasAccess(Right.VIEW, ICON_DOCUMENT_REFERENCE)).thenReturn(true); | ||
|
|
||
| List<Block> result = | ||
| this.displayIconMacro.execute(this.displayIconMacroParameters, null, new MacroTransformationContext()); | ||
| assertEquals(result, List.of(new MetaDataBlock(List.of(new WordBlock("home"))))); | ||
| verify(this.documentContextExecutor).call(any(), eq(this.iconDocument)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| .runTransformations | ||
| .#----------------------------------------------------- | ||
| .input|xwiki/2.1 | ||
| .# Verify the icon macro basic functionality | ||
| .#----------------------------------------------------- | ||
| Home icon: {{displayIcon name="home" /}} | ||
|
|
||
| {{displayIcon name="page" /}} | ||
| .#----------------------------------------------------- | ||
| .expect|event/1.0 | ||
| .#----------------------------------------------------- | ||
| beginDocument | ||
| beginParagraph | ||
| onWord [Home] | ||
| onSpace | ||
| onWord [icon] | ||
| onSpecialSymbol [:] | ||
| onSpace | ||
| beginMacroMarkerInline [displayIcon] [name=home] | ||
| beginMetaData [[syntax]=[XWiki 2.1]] | ||
| beginFormat [NONE] [[class]=[icon][data-xwiki-icon]=[homeIcon]] | ||
| onWord [i] | ||
| endFormat [NONE] [[class]=[icon][data-xwiki-icon]=[homeIcon]] | ||
| endMetaData [[syntax]=[XWiki 2.1]] | ||
| endMacroMarkerInline [displayIcon] [name=home] | ||
| endParagraph | ||
| beginMacroMarkerStandalone [displayIcon] [name=page] | ||
| beginMetaData [[syntax]=[XWiki 2.1]] | ||
| beginParagraph | ||
| beginFormat [NONE] [[class]=[icon][data-xwiki-icon]=[pageIcon]] | ||
| onWord [i] | ||
| endFormat [NONE] [[class]=[icon][data-xwiki-icon]=[pageIcon]] | ||
| endParagraph | ||
| endMetaData [[syntax]=[XWiki 2.1]] | ||
| endMacroMarkerStandalone [displayIcon] [name=page] | ||
| endDocument |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| .runTransformations | ||
| .#----------------------------------------------------- | ||
| .input|xwiki/2.1 | ||
| .# Verify that the icon set can be specified. | ||
| .#----------------------------------------------------- | ||
| {{displayIcon name="home" iconSet="special" /}} | ||
| .#----------------------------------------------------- | ||
| .expect|event/1.0 | ||
| .#----------------------------------------------------- | ||
| beginDocument | ||
| beginMacroMarkerStandalone [displayIcon] [name=home|iconSet=special] | ||
| beginMetaData [[syntax]=[XWiki 2.1]] | ||
| beginParagraph | ||
| onWord [special] | ||
| onSpace | ||
| onWord [home] | ||
| endParagraph | ||
| endMetaData [[syntax]=[XWiki 2.1]] | ||
| endMacroMarkerStandalone [displayIcon] [name=home|iconSet=special] | ||
| endDocument |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| .runTransformations | ||
| .#----------------------------------------------------- | ||
| .input|xwiki/2.1 | ||
| .# Verify that the fallback to the default works and can be disabled. | ||
| .#----------------------------------------------------- | ||
| {{displayIcon name="fallback" iconSet="special" /}} {{displayIcon name="fallback" /}} {{displayIcon name="fallback" fallback="false" /}} | ||
|
|
||
| {{displayIcon name="home" iconSet="none" fallback="false" /}} | ||
| .#----------------------------------------------------- | ||
| .expect|event/1.0 | ||
| .#----------------------------------------------------- | ||
| beginDocument | ||
| beginParagraph | ||
| beginMacroMarkerInline [displayIcon] [name=fallback|iconSet=special] | ||
| beginMetaData [[syntax]=[XWiki 2.1]] | ||
| onWord [fallback] | ||
| onSpace | ||
| onWord [fallbackIcon] | ||
| endMetaData [[syntax]=[XWiki 2.1]] | ||
| endMacroMarkerInline [displayIcon] [name=fallback|iconSet=special] | ||
| onSpace | ||
| beginMacroMarkerInline [displayIcon] [name=fallback] | ||
| beginMetaData [[syntax]=[XWiki 2.1]] | ||
| onWord [fallback] | ||
| onSpace | ||
| onWord [fallbackIcon] | ||
| endMetaData [[syntax]=[XWiki 2.1]] | ||
| endMacroMarkerInline [displayIcon] [name=fallback] | ||
| onSpace | ||
| beginMacroMarkerInline [displayIcon] [name=fallback|fallback=false] | ||
| beginMetaData | ||
| endMetaData | ||
| endMacroMarkerInline [displayIcon] [name=fallback|fallback=false] | ||
| endParagraph | ||
| beginMacroMarkerStandalone [displayIcon] [name=home|iconSet=none|fallback=false] | ||
| endMacroMarkerStandalone [displayIcon] [name=home|iconSet=none|fallback=false] | ||
| endDocument |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| .runTransformations | ||
| .#----------------------------------------------------- | ||
| .input|xwiki/2.1 | ||
| .# Verify the document-based icon set is rendered in document context | ||
| .#----------------------------------------------------- | ||
| {{displayIcon name="document" iconSet="document" /}} | ||
| .#----------------------------------------------------- | ||
| .expect|event/1.0 | ||
| .#----------------------------------------------------- | ||
| beginDocument | ||
| beginMacroMarkerStandalone [displayIcon] [name=document|iconSet=document] | ||
| beginMetaData [[source]=[xwiki:Icon.Document][syntax]=[XWiki 2.1]] | ||
| beginParagraph | ||
| onWord [document] | ||
| onSpace | ||
| onWord [executed] | ||
| endParagraph | ||
| endMetaData [[source]=[xwiki:Icon.Document][syntax]=[XWiki 2.1]] | ||
| endMacroMarkerStandalone [displayIcon] [name=document|iconSet=document] | ||
| endDocument |