diff --git a/xwiki-platform-core/xwiki-platform-mentions/xwiki-platform-mentions-notifications/pom.xml b/xwiki-platform-core/xwiki-platform-mentions/xwiki-platform-mentions-notifications/pom.xml index 130e82e88ea7cdcd13b7cf1ec04ae6b0b981a72e..5dee4c72538812d29bcec3cbac72ca6c2d232d54 100644 --- a/xwiki-platform-core/xwiki-platform-mentions/xwiki-platform-mentions-notifications/pom.xml +++ b/xwiki-platform-core/xwiki-platform-mentions/xwiki-platform-mentions-notifications/pom.xml @@ -31,7 +31,7 @@ <name>XWiki Platform - Mentions - Notifications</name> <packaging>jar</packaging> <properties> - <xwiki.jacoco.instructionRatio>0.62</xwiki.jacoco.instructionRatio> + <xwiki.jacoco.instructionRatio>0.77</xwiki.jacoco.instructionRatio> <!-- This component must be installed at the farm level because org.xwiki.eventstream.store.internal.RecordableEventListener.convertEvent uses org.xwiki.component.manager.ComponentManager. To be removed once XWIKI-17359 is fixed. --> diff --git a/xwiki-platform-core/xwiki-platform-mentions/xwiki-platform-mentions-notifications/src/main/java/org/xwiki/mentions/internal/descriptors/NotificationAdministrationDocumentInitializer.java b/xwiki-platform-core/xwiki-platform-mentions/xwiki-platform-mentions-notifications/src/main/java/org/xwiki/mentions/internal/descriptors/NotificationAdministrationDocumentInitializer.java index ed52b678548517b9822672c5cd52f95fe802701b..c8d6a9123404d3d417768836ebc5693259be060a 100644 --- a/xwiki-platform-core/xwiki-platform-mentions/xwiki-platform-mentions-notifications/src/main/java/org/xwiki/mentions/internal/descriptors/NotificationAdministrationDocumentInitializer.java +++ b/xwiki-platform-core/xwiki-platform-mentions/xwiki-platform-mentions-notifications/src/main/java/org/xwiki/mentions/internal/descriptors/NotificationAdministrationDocumentInitializer.java @@ -30,6 +30,8 @@ import org.slf4j.Logger; import org.xwiki.component.annotation.Component; +import org.xwiki.context.Execution; +import org.xwiki.context.ExecutionContext; import org.xwiki.mentions.events.MentionEvent; import org.xwiki.model.reference.LocalDocumentReference; @@ -40,8 +42,8 @@ import com.xpn.xwiki.objects.BaseObject; /** - * A Mandatory Document Intializer that aims at providing global preferences for Mentions Notifications. - * In the future, this should be replaced by a proper API in Notification to allow enabling such preferences globally. + * A Mandatory Document Intializer that aims at providing global preferences for Mentions Notifications. In the future, + * this should be replaced by a proper API in Notification to allow enabling such preferences globally. * * @version $Id$ * @since 12.6.3 @@ -59,12 +61,21 @@ public class NotificationAdministrationDocumentInitializer extends AbstractManda private static final String EVENT_TYPE_FIELD = "eventType"; + /** + * TODO: Can be removed once XWIKI-20164 is implemented. + */ + private static final String CONTEXT_MENTION_STARTDATE = + "XWiki.Notifications.Code.NotificationAdministration.mention.startDate"; + @Inject private Provider<XWikiContext> contextProvider; @Inject private Logger logger; + @Inject + private Execution execution; + /** * Default constructor. */ @@ -92,13 +103,22 @@ public boolean updateDocument(XWikiDocument document) } if (!mentionEventPreferenceAlreadySaved) { + // It is possible for several document with the "XWiki.Notifications.Code.NotificationAdministration" + // document reference to be initialized separately. We keep a date in the ExecutionContext so that + // every initialization initializes the startDate property with the same date. + // Usually initialization are static and updating the document is idempotent. This is not the case here + // because of the call to "new Date()". + ExecutionContext context = this.execution.getContext(); + if (!context.hasProperty(CONTEXT_MENTION_STARTDATE)) { + context.setProperty(CONTEXT_MENTION_STARTDATE, new Date()); + } try { int newObject = document.createXObject(notificationPreferenceClass, this.contextProvider.get()); BaseObject xObject = document.getXObject(notificationPreferenceClass, newObject); xObject.setStringValue(EVENT_TYPE_FIELD, MentionEvent.EVENT_TYPE); xObject.setStringValue("format", "alert"); xObject.setIntValue("notificationEnabled", 1); - xObject.setDateValue("startDate", new Date()); + xObject.setDateValue("startDate", (Date) context.getProperty(CONTEXT_MENTION_STARTDATE)); } catch (XWikiException e) { this.logger.error("Error while trying to set the global Notification Administration preferences " + "for mentions notifications", e); diff --git a/xwiki-platform-core/xwiki-platform-mentions/xwiki-platform-mentions-notifications/src/test/java/org/xwiki/mentions/internal/descriptors/NotificationAdministrationDocumentInitializerTest.java b/xwiki-platform-core/xwiki-platform-mentions/xwiki-platform-mentions-notifications/src/test/java/org/xwiki/mentions/internal/descriptors/NotificationAdministrationDocumentInitializerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..27cf67b81a21ec911900174ca967667150a0cc03 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-mentions/xwiki-platform-mentions-notifications/src/test/java/org/xwiki/mentions/internal/descriptors/NotificationAdministrationDocumentInitializerTest.java @@ -0,0 +1,126 @@ +/* + * 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.mentions.internal.descriptors; + +import java.util.Arrays; +import java.util.Date; + +import javax.inject.Provider; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mockito.Mock; +import org.xwiki.context.Execution; +import org.xwiki.context.ExecutionContext; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.model.reference.LocalDocumentReference; +import org.xwiki.test.LogLevel; +import org.xwiki.test.junit5.LogCaptureExtension; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xpn.xwiki.XWikiContext; +import com.xpn.xwiki.doc.XWikiDocument; +import com.xpn.xwiki.objects.BaseObject; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Test of {@link NotificationAdministrationDocumentInitializer}. + * + * @version $Id$ + * @since 14.8 + * @since 14.4.5 + * @since 13.10.10 + */ +@ComponentTest +class NotificationAdministrationDocumentInitializerTest +{ + private static final String CONTEXT_MENTION_STARTDATE = + "XWiki.Notifications.Code.NotificationAdministration.mention.startDate"; + + private static final String START_DATE_PROPERTY = "startDate"; + + @InjectMockComponents + private NotificationAdministrationDocumentInitializer initializer; + + @MockComponent + private Provider<XWikiContext> contextProvider; + + @MockComponent + private Execution execution; + + @RegisterExtension + LogCaptureExtension logCapture = new LogCaptureExtension(LogLevel.WARN); + + @Mock + private XWikiDocument document; + + @Mock + private ExecutionContext context; + + @Mock + private BaseObject baseObject; + + @BeforeEach + void setUp() throws Exception + { + XWikiContext xWikiContext = mock(XWikiContext.class); + when(this.contextProvider.get()).thenReturn(xWikiContext); + when(this.document.getDocumentReference()).thenReturn(new DocumentReference("xwiki", "Space", "Doc")); + when(this.document.getParentReference()).thenReturn(new DocumentReference("xwiki", "Space", "WebHome")); + when(this.execution.getContext()).thenReturn(this.context); + LocalDocumentReference notificationPreferenceClass = + new LocalDocumentReference(Arrays.asList("XWiki", "Notifications", "Code"), "NotificationPreferenceClass"); + when(this.document.createXObject(notificationPreferenceClass, xWikiContext)).thenReturn(12); + when(this.document.getXObject(notificationPreferenceClass, 12)).thenReturn(this.baseObject); + } + + @Test + void updateDocumentContextNotInitialized() + { + when(this.context.hasProperty(CONTEXT_MENTION_STARTDATE)).thenReturn(false); + Date date = new Date(); + when(this.context.getProperty(CONTEXT_MENTION_STARTDATE)).thenReturn(date); + this.initializer.updateDocument(this.document); + verify(this.context).setProperty(eq(CONTEXT_MENTION_STARTDATE), any(Date.class)); + verify(this.context).getProperty(CONTEXT_MENTION_STARTDATE); + verify(this.baseObject).setDateValue("startDate", date); + } + + @Test + void updateDocumentContextInitialized() + { + when(this.context.hasProperty(CONTEXT_MENTION_STARTDATE)).thenReturn(true); + Date date = new Date(); + when(this.context.getProperty(CONTEXT_MENTION_STARTDATE)).thenReturn(date); + this.initializer.updateDocument(this.document); + verify(this.context, never()).setProperty(any(), any()); + verify(this.context).getProperty(CONTEXT_MENTION_STARTDATE); + verify(this.baseObject).setDateValue(START_DATE_PROPERTY, date); + } +}