/* * 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.sheet.internal; import java.util.Arrays; import java.util.Collections; import org.junit.Assert; import org.jmock.Expectations; import org.jmock.Sequence; import org.junit.Before; import org.junit.Test; import org.xwiki.bridge.DocumentAccessBridge; import org.xwiki.bridge.DocumentModelBridge; import org.xwiki.context.Execution; import org.xwiki.context.ExecutionContext; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.DocumentReferenceResolver; import org.xwiki.sheet.SheetBinder; import org.xwiki.sheet.SheetManager; import org.xwiki.test.jmock.AbstractMockingComponentTestCase; import org.xwiki.test.annotation.AllComponents; import org.xwiki.test.jmock.annotation.MockingRequirement; /** * Unit tests for {@link DefaultSheetManager}. * * @version $Id: ace3581735cd06ec51cd867d4408d51763dbcde1 $ * @since 4.2M1 */ @AllComponents @MockingRequirement(value = DefaultSheetManager.class, exceptions = { DocumentReferenceResolver.class }) public class DefaultSheetManagerTest extends AbstractMockingComponentTestCase<SheetManager> { /** * The name of the execution context sheet property. */ private static final String SHEET_PROPERTY = "sheet"; /** * The action property of the sheet descriptor class. See {@link #SHEET_CLASS_REFERENCE}. */ private static final String ACTION_PROPERTY = "action"; /** * The name of a wiki. */ private static final String WIKI_NAME = "wiki"; /** * The sheet descriptor class reference. */ private static final DocumentReference SHEET_CLASS_REFERENCE = new DocumentReference(WIKI_NAME, "XWiki", "SheetDescriptorClass"); /** * The execution context. */ private ExecutionContext context = new ExecutionContext(); /** * The component used to access the documents. */ private DocumentAccessBridge documentAccessBridge; /** * The component used to retrieve the custom document sheets. */ private SheetBinder documentSheetBinder; /** * The component used to retrieve the class sheets. */ private SheetBinder classSheetBinder; /** * The component used to access the old model. */ private ModelBridge modelBridge; /** * The document whose sheets are retrieved. */ private DocumentModelBridge document; @Before public void configure() throws Exception { documentAccessBridge = getComponentManager().getInstance(DocumentAccessBridge.class); documentSheetBinder = getComponentManager().getInstance(SheetBinder.class, "document"); classSheetBinder = getComponentManager().getInstance(SheetBinder.class, "class"); modelBridge = getComponentManager().getInstance(ModelBridge.class); document = getMockery().mock(DocumentModelBridge.class); final Execution execution = getComponentManager().getInstance(Execution.class); getMockery().checking(new Expectations() { { allowing(execution).getContext(); will(returnValue(context)); allowing(document).getDocumentReference(); will(returnValue(new DocumentReference(WIKI_NAME, "Space", "Page"))); } }); } /** * Tests that the sheet specified on the execution context overwrites the document and class sheets. * * @throws Exception if the test fails to lookup components */ @Test public void testExecutionContextSheet() throws Exception { // (1) The sheet is specified on the execution context and the target document is the current document. context.setProperty(SHEET_PROPERTY, "Code.Sheet"); final DocumentReference sheetReference = new DocumentReference(WIKI_NAME, "Code", "Sheet"); getMockery().checking(new Expectations() { { oneOf(documentAccessBridge).getCurrentDocumentReference(); will(returnValue(document.getDocumentReference())); oneOf(documentAccessBridge).exists(sheetReference); will(returnValue(true)); // The specified sheet matches the current action. oneOf(documentAccessBridge).getProperty(sheetReference, SHEET_CLASS_REFERENCE, ACTION_PROPERTY); will(returnValue("")); } }); Assert.assertEquals(Arrays.asList(sheetReference), getMockedComponent().getSheets(document, "view")); // (2) The sheet is specified on the execution context but the target document is not the current document. getMockery().checking(new Expectations() { { oneOf(documentAccessBridge).getCurrentDocumentReference(); will(returnValue(null)); oneOf(documentSheetBinder).getSheets(document); will(returnValue(Collections.emptyList())); oneOf(modelBridge).getXObjectClassReferences(document); will(returnValue(Collections.emptySet())); } }); Assert.assertTrue(getMockedComponent().getSheets(document, "edit").isEmpty()); // (3) The sheet is not specified on the execution context. context.removeProperty(SHEET_PROPERTY); getMockery().checking(new Expectations() { { oneOf(documentSheetBinder).getSheets(document); will(returnValue(Collections.emptyList())); oneOf(modelBridge).getXObjectClassReferences(document); will(returnValue(Collections.emptySet())); } }); Assert.assertTrue(getMockedComponent().getSheets(document, "get").isEmpty()); } /** * Tests the order in which sheets are determined: execution context, document sheets and finally class sheets. * * @throws Exception shouldn't happen, but some methods include "throws" in their signature */ @Test public void testSheetResolutionSequence() throws Exception { final String contextSheetName = "ContextSheet"; context.setProperty(SHEET_PROPERTY, contextSheetName); final DocumentReference documentSheetReference = new DocumentReference(WIKI_NAME, "ABC", "DocumentSheet"); final DocumentReference classSheetReference = new DocumentReference(WIKI_NAME, "BlogCode", "BlogPostSheet"); final DocumentReference classReference = new DocumentReference(WIKI_NAME, "Blog", "BlogPostClass"); final DocumentModelBridge classDocument = getMockery().mock(DocumentModelBridge.class, "xclass"); final String currentAction = "foo"; final Sequence sheetResolutionSequence = getMockery().sequence("sheetResolutionSequence"); getMockery().checking(new Expectations() { { // (1) Look for the sheet specified in the execution context. oneOf(documentAccessBridge).getCurrentDocumentReference(); inSequence(sheetResolutionSequence); will(returnValue(document.getDocumentReference())); // The sheet is resolved relative to the target document. oneOf(documentAccessBridge).exists( new DocumentReference(document.getDocumentReference().getWikiReference().getName(), document .getDocumentReference().getLastSpaceReference().getName(), contextSheetName)); inSequence(sheetResolutionSequence); will(returnValue(false)); // (2) Look for the custom document sheets. oneOf(documentSheetBinder).getSheets(document); inSequence(sheetResolutionSequence); will(returnValue(Collections.singletonList(documentSheetReference))); oneOf(documentAccessBridge).exists(documentSheetReference); inSequence(sheetResolutionSequence); will(returnValue(true)); oneOf(documentAccessBridge).getProperty(documentSheetReference, SHEET_CLASS_REFERENCE, ACTION_PROPERTY); inSequence(sheetResolutionSequence); will(returnValue("bar")); // (3) Look for the class sheets. oneOf(modelBridge).getXObjectClassReferences(document); inSequence(sheetResolutionSequence); will(returnValue(Collections.singleton(classReference))); oneOf(documentAccessBridge).getDocument(classReference); inSequence(sheetResolutionSequence); will(returnValue(classDocument)); oneOf(classSheetBinder).getSheets(classDocument); inSequence(sheetResolutionSequence); will(returnValue(Collections.singletonList(classSheetReference))); oneOf(documentAccessBridge).exists(classSheetReference); inSequence(sheetResolutionSequence); will(returnValue(true)); oneOf(documentAccessBridge).getProperty(classSheetReference, SHEET_CLASS_REFERENCE, ACTION_PROPERTY); inSequence(sheetResolutionSequence); will(returnValue(currentAction)); } }); getMockedComponent().getSheets(document, currentAction); } }