1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package org.xwiki.refactoring.internal

File DefaultModelBridgeTest.java

 

Code metrics

2
361
32
1
795
593
33
0.09
11.28
32
1.03

Classes

Class Line # Actions
DefaultModelBridgeTest 90 361 0% 33 0
1.0100%
 

Contributing tests

This file is covered by 29 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.refactoring.internal;
21   
22    import java.util.Arrays;
23    import java.util.Collections;
24    import java.util.List;
25    import java.util.Locale;
26   
27    import javax.inject.Named;
28    import javax.inject.Provider;
29   
30    import org.junit.jupiter.api.BeforeEach;
31    import org.junit.jupiter.api.Test;
32    import org.junit.jupiter.api.extension.RegisterExtension;
33    import org.mockito.Mock;
34    import org.xwiki.job.AbstractJobStatus;
35    import org.xwiki.job.api.AbstractCheckRightsRequest;
36    import org.xwiki.job.event.status.JobProgressManager;
37    import org.xwiki.model.EntityType;
38    import org.xwiki.model.reference.DocumentReference;
39    import org.xwiki.model.reference.DocumentReferenceResolver;
40    import org.xwiki.model.reference.EntityReferenceProvider;
41    import org.xwiki.model.reference.EntityReferenceResolver;
42    import org.xwiki.model.reference.EntityReferenceSerializer;
43    import org.xwiki.model.reference.SpaceReference;
44    import org.xwiki.query.Query;
45    import org.xwiki.query.QueryManager;
46    import org.xwiki.refactoring.internal.job.PermanentlyDeleteJob;
47    import org.xwiki.test.junit5.LogCaptureExtension;
48    import org.xwiki.test.junit5.mockito.ComponentTest;
49    import org.xwiki.test.junit5.mockito.InjectMockComponents;
50    import org.xwiki.test.junit5.mockito.MockComponent;
51    import org.xwiki.test.mockito.MockitoComponentManager;
52   
53    import com.xpn.xwiki.XWiki;
54    import com.xpn.xwiki.XWikiContext;
55    import com.xpn.xwiki.doc.XWikiDeletedDocument;
56    import com.xpn.xwiki.doc.XWikiDocument;
57    import com.xpn.xwiki.internal.parentchild.ParentChildConfiguration;
58    import com.xpn.xwiki.objects.BaseObject;
59    import com.xpn.xwiki.store.XWikiRecycleBinStoreInterface;
60    import com.xpn.xwiki.user.api.XWikiRightService;
61   
62    import ch.qos.logback.classic.Level;
63    import ch.qos.logback.classic.spi.ILoggingEvent;
64   
65    import static org.hamcrest.MatcherAssert.assertThat;
66    import static org.hamcrest.Matchers.containsInAnyOrder;
67    import static org.junit.jupiter.api.Assertions.assertArrayEquals;
68    import static org.junit.jupiter.api.Assertions.assertEquals;
69    import static org.junit.jupiter.api.Assertions.assertFalse;
70    import static org.junit.jupiter.api.Assertions.assertNotNull;
71    import static org.junit.jupiter.api.Assertions.assertTrue;
72    import static org.mockito.ArgumentMatchers.any;
73    import static org.mockito.ArgumentMatchers.anyBoolean;
74    import static org.mockito.ArgumentMatchers.anyInt;
75    import static org.mockito.ArgumentMatchers.anyLong;
76    import static org.mockito.ArgumentMatchers.anyString;
77    import static org.mockito.ArgumentMatchers.eq;
78    import static org.mockito.Mockito.mock;
79    import static org.mockito.Mockito.never;
80    import static org.mockito.Mockito.times;
81    import static org.mockito.Mockito.verify;
82    import static org.mockito.Mockito.when;
83   
84    /**
85    * Unit tests for {@link DefaultModelBridge}.
86    *
87    * @version $Id: 2cd47bc3a36e1905875c3f9206ac6900983d972b $
88    */
89    @ComponentTest
 
90    public class DefaultModelBridgeTest
91    {
92    @RegisterExtension
93    LogCaptureExtension logCapture = new LogCaptureExtension();
94   
95    @InjectMockComponents
96    private DefaultModelBridge modelBridge;
97   
98    @MockComponent
99    @Named("relative")
100    private EntityReferenceResolver<String> relativeStringEntityReferenceResolver;
101   
102    @MockComponent
103    @Named("compact")
104    private EntityReferenceSerializer<String> compactEntityReferenceSerializer;
105   
106    @MockComponent
107    private JobProgressManager progressManager;
108   
109    @Mock
110    private XWikiContext xcontext;
111   
112    @Mock
113    private XWiki xwiki;
114   
115    @Mock
116    private XWikiRecycleBinStoreInterface recycleBin;
117   
118    @Mock
119    private AbstractCheckRightsRequest request;
120   
 
121  29 toggle @BeforeEach
122    public void configure(MockitoComponentManager mocker) throws Exception
123    {
124  29 when(this.xcontext.getWiki()).thenReturn(xwiki);
125  29 when(xwiki.getRecycleBinStore()).thenReturn(recycleBin);
126   
127  29 Provider<XWikiContext> xcontextProvider = mocker.getInstance(XWikiContext.TYPE_PROVIDER);
128  29 when(xcontextProvider.get()).thenReturn(this.xcontext);
129   
130  29 EntityReferenceProvider entityReferenceProvider = mocker.getInstance(EntityReferenceProvider.class);
131  29 when(entityReferenceProvider.getDefaultReference(EntityType.DOCUMENT))
132    .thenReturn(new DocumentReference("what", "ever", "WebHome"));
133  29 when(entityReferenceProvider.getDefaultReference(EntityType.SPACE))
134    .thenReturn(new SpaceReference("whatever", "Main"));
135    }
136   
 
137  18 toggle private void assertLog(Level level, String message, Object... arguments)
138    {
139  18 ILoggingEvent log = this.logCapture.getLogEvent(0);
140  18 assertEquals(level, log.getLevel());
141  18 assertEquals(message, log.getMessage());
142  18 assertArrayEquals(arguments, log.getArgumentArray());
143    }
144   
 
145  14 toggle private void assertLog(int i, Level level, String message, Object... arguments)
146    {
147  14 ILoggingEvent log = this.logCapture.getLogEvent(i);
148  14 assertEquals(level, log.getLevel());
149  14 assertEquals(message, log.getMessage());
150  14 assertArrayEquals(arguments, log.getArgumentArray());
151    }
152   
 
153  1 toggle @Test
154    public void create(MockitoComponentManager mocker) throws Exception
155    {
156  1 XWikiDocument document = mock(XWikiDocument.class);
157  1 DocumentReference documentReference = new DocumentReference("wiki", "Space", "Page");
158  1 when(this.xcontext.getWiki().getDocument(documentReference, this.xcontext)).thenReturn(document);
159   
160  1 this.modelBridge.create(documentReference);
161   
162  1 verify(this.xcontext.getWiki()).saveDocument(document, this.xcontext);
163  1 assertLog(Level.INFO, "Document [{}] has been created.", documentReference);
164    }
165   
 
166  1 toggle @Test
167    public void copy() throws Exception
168    {
169  1 DocumentReference sourceReference = new DocumentReference("wiki", "Space", "Page", Locale.FRENCH);
170  1 DocumentReference copyReference = new DocumentReference("wiki", "Space", "Copy");
171   
172  1 when(this.xcontext.getWiki().copyDocument(sourceReference, copyReference, "fr", false, true, true,
173    this.xcontext)).thenReturn(true);
174   
175  1 assertTrue(this.modelBridge.copy(sourceReference, copyReference));
176  1 assertLog(Level.INFO, "Document [{}] has been copied to [{}].", sourceReference, copyReference);
177    }
178   
 
179  1 toggle @Test
180    public void deleteTranslation() throws Exception
181    {
182  1 XWikiDocument sourceDocument = mock(XWikiDocument.class);
183  1 DocumentReference sourceReference = new DocumentReference("wiki", "Space", "Page", Locale.FRENCH);
184  1 when(this.xcontext.getWiki().getDocument(sourceReference, this.xcontext)).thenReturn(sourceDocument);
185  1 when(sourceDocument.getTranslation()).thenReturn(1);
186   
187  1 this.modelBridge.delete(sourceReference);
188   
189  1 verify(this.xcontext.getWiki()).deleteDocument(sourceDocument, this.xcontext);
190  1 assertLog(Level.INFO, "Document [{}] has been deleted.", sourceReference);
191    }
192   
 
193  1 toggle @Test
194    public void deleteAllTranslations() throws Exception
195    {
196  1 DocumentReference sourceReference = new DocumentReference("wiki", "Space", "Page");
197   
198  1 XWikiDocument sourceDocument = mock(XWikiDocument.class);
199  1 when(this.xcontext.getWiki().getDocument(sourceReference, this.xcontext)).thenReturn(sourceDocument);
200  1 when(sourceDocument.getTranslation()).thenReturn(0);
201   
202  1 this.modelBridge.delete(sourceReference);
203   
204  1 verify(this.xcontext.getWiki()).deleteAllDocuments(sourceDocument, this.xcontext);
205  1 assertLog(Level.INFO, "Document [{}] has been deleted with all its translations.", sourceReference);
206    }
207   
 
208  1 toggle @Test
209    public void createRedirect() throws Exception
210    {
211  1 DocumentReference oldReference = new DocumentReference("wiki", "Space", "Old");
212  1 DocumentReference newReference = new DocumentReference("wiki", "Space", "New");
213   
214  1 DocumentReference redirectClassReference = new DocumentReference("wiki", "XWiki", "RedirectClass");
215  1 when(this.xcontext.getWiki().exists(redirectClassReference, this.xcontext)).thenReturn(true);
216   
217  1 XWikiDocument oldDocument = mock(XWikiDocument.class);
218  1 when(this.xcontext.getWiki().getDocument(oldReference, this.xcontext)).thenReturn(oldDocument);
219  1 when(oldDocument.getXObject(eq(redirectClassReference), anyInt())).thenReturn(mock(BaseObject.class));
220   
221  1 this.modelBridge.createRedirect(oldReference, newReference);
222   
223  1 verify(oldDocument).setHidden(true);
224  1 verify(this.xcontext.getWiki()).saveDocument(oldDocument, "Create automatic redirect.", this.xcontext);
225  1 assertLog(Level.INFO, "Created automatic redirect from [{}] to [{}].", oldReference, newReference);
226    }
227   
 
228  1 toggle @Test
229    public void getDocumentReferences(MockitoComponentManager mocker) throws Exception
230    {
231  1 SpaceReference spaceReference = new SpaceReference("wiki", "Space");
232   
233  1 Query query = mock(Query.class);
234  1 QueryManager queryManager = mocker.getInstance(QueryManager.class);
235  1 when(queryManager.createQuery(any(), any())).thenReturn(query);
236   
237  1 EntityReferenceSerializer<String> localEntityReferenceSerializer =
238    mocker.getInstance(EntityReferenceSerializer.TYPE_STRING, "local");
239  1 when(localEntityReferenceSerializer.serialize(spaceReference)).thenReturn("Space");
240   
241  1 when(query.execute()).thenReturn(Arrays.<Object>asList("Page"));
242   
243  1 DocumentReferenceResolver<String> explicitDocumentReferenceResolver =
244    mocker.getInstance(DocumentReferenceResolver.TYPE_STRING, "explicit");
245  1 DocumentReference documentReference = new DocumentReference("Page", spaceReference);
246  1 when(explicitDocumentReferenceResolver.resolve("Page", spaceReference)).thenReturn(documentReference);
247   
248  1 assertEquals(Arrays.asList(documentReference), this.modelBridge.getDocumentReferences(spaceReference));
249   
250  1 verify(query).setWiki(spaceReference.getWikiReference().getName());
251  1 verify(query).bindValue("space", "Space");
252  1 verify(query).bindValue("spacePrefix", "Space.%");
253    }
254   
 
255  1 toggle @Test
256    public void updateParentFields(MockitoComponentManager mocker) throws Exception
257    {
258  1 DocumentReference oldParentReference = new DocumentReference("wiki", "Space", "Old");
259  1 DocumentReference newParentReference = new DocumentReference("wiki", "Space", "New");
260   
261  1 XWikiDocument oldParentDocument = mock(XWikiDocument.class);
262  1 when(this.xcontext.getWiki().getDocument(oldParentReference, this.xcontext)).thenReturn(oldParentDocument);
263   
264  1 DocumentReference child1Reference = new DocumentReference("wiki", "Space", "Child1");
265  1 DocumentReference child2Reference = new DocumentReference("wiki", "Space", "Child2");
266  1 when(oldParentDocument.getChildrenReferences(this.xcontext))
267    .thenReturn(Arrays.asList(child1Reference, child2Reference));
268   
269  1 JobProgressManager mockProgressManager = mocker.getInstance(JobProgressManager.class);
270   
271  1 XWikiDocument child1Document = mock(XWikiDocument.class);
272  1 when(this.xcontext.getWiki().getDocument(child1Reference, this.xcontext)).thenReturn(child1Document);
273  1 XWikiDocument child2Document = mock(XWikiDocument.class);
274  1 when(this.xcontext.getWiki().getDocument(child2Reference, this.xcontext)).thenReturn(child2Document);
275   
276  1 this.modelBridge.updateParentField(oldParentReference, newParentReference);
277   
278  1 verify(mockProgressManager).pushLevelProgress(2, this.modelBridge);
279   
280  1 verify(child1Document).setParentReference(newParentReference);
281  1 verify(this.xcontext.getWiki()).saveDocument(child1Document, "Updated parent field.", true, this.xcontext);
282   
283  1 verify(child2Document).setParentReference(newParentReference);
284  1 verify(this.xcontext.getWiki()).saveDocument(child1Document, "Updated parent field.", true, this.xcontext);
285   
286  1 assertLog(Level.INFO, "Document parent fields updated from [{}] to [{}] for [{}] documents.",
287    oldParentReference, newParentReference, 2);
288    }
289   
 
290  1 toggle @Test
291    public void updateParentFieldsNoChildren(MockitoComponentManager mocker) throws Exception
292    {
293  1 DocumentReference oldParentReference = new DocumentReference("wiki", "Space", "Old");
294  1 DocumentReference newParentReference = new DocumentReference("wiki", "Space", "New");
295   
296  1 XWikiDocument oldParentDocument = mock(XWikiDocument.class);
297  1 when(this.xcontext.getWiki().getDocument(oldParentReference, this.xcontext)).thenReturn(oldParentDocument);
298   
299  1 when(oldParentDocument.getChildrenReferences(this.xcontext))
300    .thenReturn(Collections.<DocumentReference>emptyList());
301   
302  1 JobProgressManager mockProgressManager = mocker.getInstance(JobProgressManager.class);
303   
304  1 this.modelBridge.updateParentField(oldParentReference, newParentReference);
305   
306  1 verify(mockProgressManager, never()).pushLevelProgress(anyInt(), any());
307  1 verify(this.xcontext.getWiki(), never()).saveDocument(any(XWikiDocument.class), eq("Updated parent field."),
308    eq(true), eq(this.xcontext));
309    }
310   
 
311  1 toggle @Test
312    public void updateTitle() throws Exception
313    {
314  1 DocumentReference documentReference = new DocumentReference("wiki", Arrays.asList("Path", "To"), "Page");
315  1 XWikiDocument document = mock(XWikiDocument.class);
316  1 when(this.xcontext.getWiki().getDocument(documentReference, xcontext)).thenReturn(document);
317   
318  1 DocumentReference hierarchicalParent = new DocumentReference("wiki", Arrays.asList("Path", "To"), "WebHome");
319  1 String serializedParent = "xwiki:Path.To.WebHome";
320  1 when(this.compactEntityReferenceSerializer.serialize(hierarchicalParent, documentReference)).thenReturn(serializedParent);
321  1 when(this.relativeStringEntityReferenceResolver.resolve(serializedParent, EntityType.DOCUMENT))
322    .thenReturn(hierarchicalParent);
323   
324  1 this.modelBridge.update(documentReference, Collections.singletonMap("title", "foo"));
325   
326  1 verify(document).setTitle("foo");
327  1 verify(this.xcontext.getWiki()).saveDocument(document, "Update document after refactoring.", true, xcontext);
328  1 assertLog(Level.INFO, "Document [{}] has been updated.", documentReference);
329    }
330   
 
331  1 toggle @Test
332    public void updateParentWhenPageIsTerminal() throws Exception
333    {
334  1 DocumentReference documentReference = new DocumentReference("wiki", Arrays.asList("Path", "To"), "Page");
335  1 XWikiDocument document = mock(XWikiDocument.class);
336  1 when(this.xcontext.getWiki().getDocument(documentReference, xcontext)).thenReturn(document);
337  1 when(document.getParentReference()).thenReturn(new DocumentReference("wiki", "What", "Ever"));
338  1 DocumentReference hierarchicalParent = new DocumentReference("wiki", Arrays.asList("Path", "To"), "WebHome");
339  1 String serializedParent = "xwiki:Path.To.WebHome";
340  1 when(this.compactEntityReferenceSerializer.serialize(hierarchicalParent, documentReference)).thenReturn(serializedParent);
341  1 when(this.relativeStringEntityReferenceResolver.resolve(serializedParent, EntityType.DOCUMENT))
342    .thenReturn(hierarchicalParent.getLocalDocumentReference());
343   
344  1 this.modelBridge.update(documentReference, Collections.emptyMap());
345   
346  1 verify(document).setParentReference(hierarchicalParent.getLocalDocumentReference());
347  1 verify(this.xcontext.getWiki()).saveDocument(document, "Update document after refactoring.", true, xcontext);
348  1 assertLog(Level.INFO, "Document [{}] has been updated.", documentReference);
349    }
350   
 
351  1 toggle @Test
352    public void dontUpdateParentDifferentWikiSameSpace() throws Exception
353    {
354  1 DocumentReference documentReference = new DocumentReference("wiki", Arrays.asList("Path", "To"), "Page");
355  1 XWikiDocument document = mock(XWikiDocument.class);
356  1 when(this.xcontext.getWiki().getDocument(documentReference, xcontext)).thenReturn(document);
357   
358  1 DocumentReference parentReference = new DocumentReference("subwiki", Arrays.asList("Path", "To"), "WebHome");
359  1 when(document.getParentReference()).thenReturn(parentReference);
360  1 when(document.getRelativeParentReference()).thenReturn(parentReference.getLocalDocumentReference());
361   
362  1 DocumentReference hierarchicalParent = new DocumentReference("wiki", Arrays.asList("Path", "To"), "WebHome");
363  1 String serializedParent = "wiki:Path.To.WebHome";
364  1 when(this.compactEntityReferenceSerializer.serialize(hierarchicalParent, documentReference)).thenReturn(serializedParent);
365  1 when(this.relativeStringEntityReferenceResolver.resolve(serializedParent, EntityType.DOCUMENT))
366    .thenReturn(hierarchicalParent.getLocalDocumentReference());
367   
368  1 this.modelBridge.update(documentReference, Collections.emptyMap());
369   
370    // no need to update the parent: different wiki but same relative reference
371  1 verify(document, never()).setParentReference(hierarchicalParent.getLocalDocumentReference());
372  1 verify(this.xcontext.getWiki(), never()).saveDocument(document, "Update document after refactoring.", true, xcontext);
373    }
374   
 
375  1 toggle @Test
376    public void dontUpdateParentInCaseOfPageRename() throws Exception
377    {
378  1 DocumentReference documentReference = new DocumentReference("wiki", Arrays.asList("Path", "Foo"), "WebHome");
379  1 XWikiDocument document = mock(XWikiDocument.class);
380  1 when(this.xcontext.getWiki().getDocument(documentReference, xcontext)).thenReturn(document);
381   
382  1 DocumentReference parentReference = new DocumentReference("wiki", Arrays.asList("Path"), "WebHome");
383  1 when(document.getParentReference()).thenReturn(parentReference);
384  1 when(document.getRelativeParentReference()).thenReturn(parentReference.getLocalDocumentReference());
385   
386  1 DocumentReference hierarchicalParent = new DocumentReference("wiki", Arrays.asList("Path"), "WebHome");
387  1 String serializedParent = "wiki:Path.WebHome";
388  1 when(this.compactEntityReferenceSerializer.serialize(hierarchicalParent, documentReference)).thenReturn(serializedParent);
389  1 when(this.relativeStringEntityReferenceResolver.resolve(serializedParent, EntityType.DOCUMENT))
390    .thenReturn(hierarchicalParent.getLocalDocumentReference());
391   
392  1 this.modelBridge.update(documentReference, Collections.emptyMap());
393   
394    // no need to update the parent: different name but same parents
395  1 verify(document, never()).setParentReference(hierarchicalParent.getLocalDocumentReference());
396  1 verify(this.xcontext.getWiki(), never()).saveDocument(document, "Update document after refactoring.", true, xcontext);
397    }
398   
 
399  1 toggle @Test
400    public void updateParentWhenPageIsNested() throws Exception
401    {
402  1 DocumentReference documentReference = new DocumentReference("wiki", Arrays.asList("Path", "To"), "WebHome");
403  1 XWikiDocument document = mock(XWikiDocument.class);
404  1 when(this.xcontext.getWiki().getDocument(documentReference, xcontext)).thenReturn(document);
405  1 when(document.getParentReference()).thenReturn(new DocumentReference("wiki", "What", "Ever"));
406  1 DocumentReference hierarchicalParent = new DocumentReference("wiki", "Path", "WebHome");
407  1 String serializedParent = "xwiki:Path.WebHome";
408  1 when(this.compactEntityReferenceSerializer.serialize(hierarchicalParent, documentReference)).thenReturn(serializedParent);
409  1 when(this.relativeStringEntityReferenceResolver.resolve(serializedParent, EntityType.DOCUMENT))
410    .thenReturn(hierarchicalParent.getLocalDocumentReference());
411   
412  1 this.modelBridge.update(documentReference, Collections.emptyMap());
413   
414  1 verify(document).setParentReference(hierarchicalParent.getLocalDocumentReference());
415  1 verify(this.xcontext.getWiki()).saveDocument(document, "Update document after refactoring.", true, xcontext);
416  1 assertLog(Level.INFO, "Document [{}] has been updated.", documentReference);
417    }
418   
 
419  1 toggle @Test
420    public void updateParentWhenPageIsTopLevel() throws Exception
421    {
422  1 DocumentReference documentReference = new DocumentReference("wiki", "Path", "WebHome");
423  1 XWikiDocument document = mock(XWikiDocument.class);
424  1 when(this.xcontext.getWiki().getDocument(documentReference, xcontext)).thenReturn(document);
425  1 when(document.getParentReference()).thenReturn(new DocumentReference("wiki", "What", "Ever"));
426   
427  1 DocumentReference hierarchicalParent = new DocumentReference("wiki", "Main", "WebHome");
428  1 String serializedParent = "xwiki:Main.WebHome";
429  1 when(this.compactEntityReferenceSerializer.serialize(hierarchicalParent, documentReference)).thenReturn(serializedParent);
430  1 when(this.relativeStringEntityReferenceResolver.resolve(serializedParent, EntityType.DOCUMENT))
431    .thenReturn(hierarchicalParent.getLocalDocumentReference());
432   
433  1 this.modelBridge.update(documentReference, Collections.emptyMap());
434   
435  1 verify(document).setParentReference(hierarchicalParent.getLocalDocumentReference());
436  1 verify(this.xcontext.getWiki()).saveDocument(document, "Update document after refactoring.", true, xcontext);
437  1 assertLog(Level.INFO, "Document [{}] has been updated.", documentReference);
438    }
439   
 
440  1 toggle @Test
441    public void dontUpdateParentWhenLegacyMode(MockitoComponentManager mocker) throws Exception
442    {
443  1 DocumentReference documentReference = new DocumentReference("wiki", Arrays.asList("Path", "To"), "Page");
444  1 XWikiDocument document = mock(XWikiDocument.class);
445  1 when(this.xcontext.getWiki().getDocument(documentReference, xcontext)).thenReturn(document);
446  1 when(document.getParentReference()).thenReturn(new DocumentReference("wiki", "What", "Ever"));
447   
448  1 ParentChildConfiguration parentChildConfiguration = mocker.getInstance(ParentChildConfiguration.class);
449  1 when(parentChildConfiguration.isParentChildMechanismEnabled()).thenReturn(true);
450   
451  1 this.modelBridge.update(documentReference, Collections.emptyMap());
452   
453  1 verify(document, never()).setParentReference(any(DocumentReference.class));
454  1 verify(this.xcontext.getWiki(), never()).saveDocument(any(XWikiDocument.class), anyString(), anyBoolean(),
455    any(XWikiContext.class));
456    }
457   
 
458  1 toggle @Test
459    public void getBackLinkedReferences() throws Exception
460    {
461  1 DocumentReference documentReference = new DocumentReference("alice", Arrays.asList("Path", "To"), "Page");
462  1 XWikiDocument document = mock(XWikiDocument.class);
463  1 when(this.xcontext.getWiki().getDocument(documentReference, this.xcontext)).thenReturn(document);
464   
465  1 List<DocumentReference> backLinks = Arrays.asList(new DocumentReference("bob", "One", "Two"));
466  1 when(document.getBackLinkedReferences(this.xcontext)).thenReturn(backLinks);
467   
468  1 this.xcontext.setWikiId("carol");
469   
470  1 assertEquals(backLinks, this.modelBridge.getBackLinkedReferences(documentReference, "bob"));
471   
472  1 verify(this.xcontext).setWikiId("bob");
473  1 verify(this.xcontext).setWikiId("carol");
474    }
475   
 
476  1 toggle @Test
477    public void restoreDeletedDocument() throws Exception
478    {
479  1 long deletedDocumentId = 42;
480  1 DocumentReference documentReference = new DocumentReference("wiki", "space", "page");
481   
482  1 XWikiDeletedDocument deletedDocument = mock(XWikiDeletedDocument.class);
483  1 when(deletedDocument.getDocumentReference()).thenReturn(documentReference);
484  1 when(deletedDocument.getId()).thenReturn(deletedDocumentId);
485  1 when(xwiki.getDeletedDocument(deletedDocumentId, xcontext)).thenReturn(deletedDocument);
486   
487  1 when(xwiki.exists(documentReference, xcontext)).thenReturn(false);
488  1 when(request.isCheckAuthorRights()).thenReturn(false);
489  1 when(request.isCheckRights()).thenReturn(false);
490   
491  1 assertTrue(this.modelBridge.restoreDeletedDocument(deletedDocumentId, request));
492   
493  1 verify(xwiki).restoreFromRecycleBin(deletedDocumentId, "Restored from recycle bin", xcontext);
494  1 assertLog(Level.INFO, "Document [{}] has been restored", documentReference);
495    }
496   
 
497  1 toggle @Test
498    public void permanentlyDeleteDeletedDocument() throws Exception
499    {
500  1 long deletedDocumentId = 42;
501  1 DocumentReference documentReference = new DocumentReference("wiki", "space", "page");
502   
503  1 XWikiDeletedDocument deletedDocument = mock(XWikiDeletedDocument.class);
504  1 when(deletedDocument.getDocumentReference()).thenReturn(documentReference);
505  1 when(deletedDocument.getId()).thenReturn(deletedDocumentId);
506  1 when(xwiki.getDeletedDocument(deletedDocumentId, xcontext)).thenReturn(deletedDocument);
507   
508  1 when(xwiki.exists(documentReference, xcontext)).thenReturn(false);
509  1 when(request.isCheckAuthorRights()).thenReturn(false);
510  1 when(request.isCheckRights()).thenReturn(false);
511   
512  1 assertTrue(this.modelBridge.permanentlyDeleteDocument(deletedDocumentId, request));
513   
514  1 verify(recycleBin).deleteFromRecycleBin(deletedDocumentId, xcontext, true);
515  1 assertLog(Level.INFO, "Document [{}] has been permanently deleted.", documentReference);
516    }
517   
 
518  1 toggle @Test
519    public void restoreDeletedDocumentInvalidId() throws Exception
520    {
521  1 long deletedDocumentId = 42;
522   
523  1 when(xwiki.getDeletedDocument(deletedDocumentId, xcontext)).thenReturn(null);
524  1 when(request.isCheckAuthorRights()).thenReturn(false);
525  1 when(request.isCheckRights()).thenReturn(false);
526   
527  1 assertFalse(this.modelBridge.restoreDeletedDocument(deletedDocumentId, request));
528   
529  1 assertLog(Level.ERROR, "Deleted document with ID [{}] does not exist.", deletedDocumentId);
530   
531  1 verify(xwiki, never()).restoreFromRecycleBin(any(), any(), any());
532    }
533   
 
534  1 toggle @Test
535    public void permanentlyDeleteDeletedDocumentInvalidId() throws Exception
536    {
537  1 long deletedDocumentId = 42;
538   
539  1 when(xwiki.getDeletedDocument(deletedDocumentId, xcontext)).thenReturn(null);
540  1 when(request.isCheckAuthorRights()).thenReturn(false);
541  1 when(request.isCheckRights()).thenReturn(false);
542   
543  1 assertFalse(this.modelBridge.permanentlyDeleteDocument(deletedDocumentId, request));
544   
545  1 assertLog(Level.ERROR, "Deleted document with ID [{}] does not exist.", deletedDocumentId);
546   
547  1 verify(recycleBin, never()).deleteFromRecycleBin(anyLong(), any(), anyBoolean());
548    }
549   
 
550  1 toggle @Test
551    public void restoreDeletedDocumentAlreadyExists() throws Exception
552    {
553  1 long deletedDocumentId = 42;
554  1 DocumentReference documentReference = new DocumentReference("wiki", "space", "page");
555  1 String fullName = "space.page";
556   
557  1 XWikiDeletedDocument deletedDocument = mock(XWikiDeletedDocument.class);
558  1 when(deletedDocument.getDocumentReference()).thenReturn(documentReference);
559  1 when(deletedDocument.getId()).thenReturn(deletedDocumentId);
560  1 when(deletedDocument.getFullName()).thenReturn(fullName);
561  1 when(xwiki.getDeletedDocument(deletedDocumentId, xcontext)).thenReturn(deletedDocument);
562   
563  1 when(xwiki.exists(documentReference, xcontext)).thenReturn(true);
564  1 when(request.isCheckAuthorRights()).thenReturn(false);
565  1 when(request.isCheckRights()).thenReturn(false);
566   
567  1 assertFalse(this.modelBridge.restoreDeletedDocument(deletedDocumentId, request));
568   
569  1 assertLog(Level.ERROR, "Document [{}] with ID [{}] can not be restored. Document already exists", fullName,
570    deletedDocumentId);
571   
572  1 verify(xwiki, never()).restoreFromRecycleBin(any(), any(), any());
573    }
574   
575    /**
576    * @see "XWIKI-9567: Cannot restore document translations from recycle bin"
577    */
 
578  1 toggle @Test
579    public void restoreDocumentTranslation() throws Exception
580    {
581  1 long deletedDocumentId = 42;
582  1 Locale locale = new Locale("ro");
583  1 DocumentReference documentReference = new DocumentReference("wiki", "space", "page");
584  1 DocumentReference translationDocumentReference = new DocumentReference(documentReference, locale);
585   
586  1 XWikiDeletedDocument deletedDocument = mock(XWikiDeletedDocument.class);
587  1 when(deletedDocument.getDocumentReference()).thenReturn(translationDocumentReference);
588  1 when(deletedDocument.getId()).thenReturn(deletedDocumentId);
589  1 when(xwiki.getDeletedDocument(deletedDocumentId, xcontext)).thenReturn(deletedDocument);
590   
591  1 when(xwiki.exists(translationDocumentReference, xcontext)).thenReturn(false);
592  1 when(request.isCheckAuthorRights()).thenReturn(false);
593  1 when(request.isCheckRights()).thenReturn(false);
594   
595  1 assertTrue(this.modelBridge.restoreDeletedDocument(deletedDocumentId, request));
596   
597  1 verify(xwiki).restoreFromRecycleBin(deletedDocumentId, "Restored from recycle bin", xcontext);
598  1 assertLog(Level.INFO, "Document [{}] has been restored", translationDocumentReference);
599   
600    // Make sure that the main document is not checked for existence, but the translated document which we actually
601    // want to restore.
602  1 verify(xwiki, never()).exists(documentReference, xcontext);
603  1 verify(xwiki).exists(translationDocumentReference, xcontext);
604    }
605   
 
606  1 toggle @Test
607    public void permanentlyDeleteDocumentTranslation() throws Exception
608    {
609  1 long deletedDocumentId = 42;
610  1 Locale locale = new Locale("ro");
611  1 DocumentReference documentReference = new DocumentReference("wiki", "space", "page");
612  1 DocumentReference translationDocumentReference = new DocumentReference(documentReference, locale);
613   
614  1 XWikiDeletedDocument deletedDocument = mock(XWikiDeletedDocument.class);
615  1 when(deletedDocument.getDocumentReference()).thenReturn(translationDocumentReference);
616  1 when(deletedDocument.getId()).thenReturn(deletedDocumentId);
617  1 when(xwiki.getDeletedDocument(deletedDocumentId, xcontext)).thenReturn(deletedDocument);
618   
619  1 when(xwiki.exists(translationDocumentReference, xcontext)).thenReturn(false);
620  1 when(request.isCheckAuthorRights()).thenReturn(false);
621  1 when(request.isCheckRights()).thenReturn(false);
622   
623  1 assertTrue(this.modelBridge.permanentlyDeleteDocument(deletedDocumentId, request));
624   
625  1 verify(recycleBin).deleteFromRecycleBin(deletedDocumentId, xcontext, true);
626  1 assertLog(Level.INFO, "Document [{}] has been permanently deleted.", translationDocumentReference);
627    }
628   
 
629  1 toggle @Test
630    public void canRestoreDeletedDocument() throws Exception
631    {
632  1 long deletedDocumentId = 42;
633  1 String deletedDocumentFullName = "Space.DeletedDocument";
634   
635  1 DocumentReference userReferenceToCheck = new DocumentReference("wiki", "Space", "User");
636   
637  1 DocumentReference currentUserReference = new DocumentReference("wiki", "Space", "CurrentUser");
638   
639  1 when(xcontext.getUserReference()).thenReturn(currentUserReference);
640   
641  1 XWikiDeletedDocument deletedDocument = mock(XWikiDeletedDocument.class);
642  1 when(deletedDocument.getFullName()).thenReturn(deletedDocumentFullName);
643   
644  1 XWikiRightService rightService = mock(XWikiRightService.class);
645  1 when(xwiki.getRightService()).thenReturn(rightService);
646  1 when(rightService.hasAccessLevel(any(), any(), any(), any())).thenReturn(true);
647   
648  1 assertTrue(this.modelBridge.canRestoreDeletedDocument(deletedDocument, userReferenceToCheck));
649   
650    // Verify that the rights were checked with the specified user as context user.
651  1 verify(xcontext).setUserReference(userReferenceToCheck);
652    // Verify that the context user was restored. Note: We don`t know the order here, but maybe we don`t care that
653    // much.
654  1 verify(xcontext).setUserReference(currentUserReference);
655    }
656   
 
657  1 toggle @Test
658    public void restoreDeletedDocumentNoRights() throws Exception
659    {
660  1 long deletedDocumentId = 42;
661  1 DocumentReference documentReference = new DocumentReference("wiki", "space", "page");
662  1 String deletedDocumentFullName = "space.page";
663   
664  1 XWikiDeletedDocument deletedDocument = mock(XWikiDeletedDocument.class);
665  1 when(deletedDocument.getDocumentReference()).thenReturn(documentReference);
666  1 when(deletedDocument.getId()).thenReturn(deletedDocumentId);
667  1 when(deletedDocument.getFullName()).thenReturn(deletedDocumentFullName);
668  1 when(xwiki.getDeletedDocument(deletedDocumentId, xcontext)).thenReturn(deletedDocument);
669   
670  1 when(xwiki.exists(documentReference, xcontext)).thenReturn(false);
671  1 when(recycleBin.getDeletedDocument(deletedDocumentId, xcontext, true)).thenReturn(deletedDocument);
672   
673    // No rights.
674  1 XWikiRightService rightService = mock(XWikiRightService.class);
675  1 when(xwiki.getRightService()).thenReturn(rightService);
676  1 when(rightService.hasAccessLevel(any(), any(), any(), any())).thenReturn(false);
677  1 DocumentReference authorReference = new DocumentReference("wiki", "user", "Alice");
678  1 when(xcontext.getAuthorReference()).thenReturn(authorReference);
679  1 when(request.isCheckRights()).thenReturn(true);
680  1 when(request.isCheckAuthorRights()).thenReturn(true);
681   
682  1 assertFalse(this.modelBridge.restoreDeletedDocument(deletedDocumentId, request));
683   
684  1 assertLog(Level.ERROR, "The author [{}] of this script is not allowed to restore document [{}] with ID [{}]",
685    authorReference, documentReference, deletedDocumentId);
686  1 verify(xwiki, never()).restoreFromRecycleBin(any(), any(), any());
687    }
688   
 
689  1 toggle @Test
690    public void permanentlyDeleteDeletedDocumentNoRights() throws Exception
691    {
692  1 long deletedDocumentId = 42;
693  1 DocumentReference documentReference = new DocumentReference("wiki", "space", "page");
694  1 String deletedDocumentFullName = "space.page";
695   
696  1 XWikiDeletedDocument deletedDocument = mock(XWikiDeletedDocument.class);
697  1 when(deletedDocument.getDocumentReference()).thenReturn(documentReference);
698  1 when(deletedDocument.getId()).thenReturn(deletedDocumentId);
699  1 when(deletedDocument.getFullName()).thenReturn(deletedDocumentFullName);
700  1 when(xwiki.getDeletedDocument(deletedDocumentId, xcontext)).thenReturn(deletedDocument);
701   
702  1 when(xwiki.exists(documentReference, xcontext)).thenReturn(false);
703  1 when(recycleBin.getDeletedDocument(deletedDocumentId, xcontext, true)).thenReturn(deletedDocument);
704   
705    // No rights.
706  1 XWikiRightService rightService = mock(XWikiRightService.class);
707  1 when(xwiki.getRightService()).thenReturn(rightService);
708  1 when(rightService.hasAccessLevel(any(), any(), any(), any())).thenReturn(false);
709  1 when(request.isCheckRights()).thenReturn(true);
710  1 when(request.isCheckAuthorRights()).thenReturn(true);
711   
712  1 assertFalse(this.modelBridge.permanentlyDeleteDocument(deletedDocumentId, request));
713   
714  1 assertLog(0, Level.WARN, "Exception while checking if entry [{}] can be removed from the recycle bin",
715    deletedDocumentId);
716  1 assertLog(1, Level.ERROR, "You are not allowed to permanently delete document [{}] with ID [{}]",
717    documentReference, deletedDocumentId);
718  1 verify(recycleBin, never()).deleteFromRecycleBin(anyLong(), any(), anyBoolean());
719    }
720   
 
721  1 toggle @Test
722    public void getDeletedDocumentIds() throws Exception
723    {
724  1 String batchId = "abc123";
725  1 long id1 = 1;
726  1 long id2 = 2;
727  1 XWikiDeletedDocument deletedDocument1 = mock(XWikiDeletedDocument.class);
728  1 when(deletedDocument1.getId()).thenReturn(id1);
729   
730  1 XWikiDeletedDocument deletedDocument2 = mock(XWikiDeletedDocument.class);
731  1 when(deletedDocument2.getId()).thenReturn(id2);
732   
733  1 XWikiDeletedDocument[] deletedDocuments = {deletedDocument1, deletedDocument2};
734   
735  1 when(recycleBin.getAllDeletedDocuments(batchId, false, xcontext, true)).thenReturn(deletedDocuments);
736  1 when(xwiki.getRecycleBinStore()).thenReturn(recycleBin);
737   
738  1 List<Long> result = this.modelBridge.getDeletedDocumentIds(batchId);
739   
740  1 assertNotNull(result);
741  1 assertEquals(deletedDocuments.length, result.size());
742  1 assertThat(result, containsInAnyOrder(id1, id2));
743    }
744   
 
745  1 toggle @Test
746    public void canOverwriteSilently() throws Exception
747    {
748  1 DocumentReference documentReference = new DocumentReference("wiki", Arrays.asList("Path", "To"), "Page");
749  1 XWikiDocument document = mock(XWikiDocument.class);
750  1 when(this.xwiki.getDocument(documentReference, this.xcontext)).thenReturn(document);
751   
752  1 assertFalse(this.modelBridge.canOverwriteSilently(documentReference));
753   
754  1 DocumentReference redirectClassReference = new DocumentReference("wiki", "XWiki", "RedirectClass");
755  1 when(document.getXObject(redirectClassReference)).thenReturn(mock(BaseObject.class));
756   
757  1 assertTrue(this.modelBridge.canOverwriteSilently(documentReference));
758    }
759   
 
760  1 toggle @Test
761    public void permanentlyDeleteAllDocuments() throws Exception
762    {
763  1 int nbDocs = 12;
764  1 PermanentlyDeleteJob deleteJob = mock(PermanentlyDeleteJob.class);
765  1 AbstractJobStatus jobStatus = mock(AbstractJobStatus.class);
766  1 when(jobStatus.isCanceled()).thenReturn(false);
767  1 when(deleteJob.getStatus()).thenReturn(jobStatus);
768   
769  1 DocumentReference documentReference = new DocumentReference("wiki", "space", "page");
770  1 XWikiDeletedDocument deletedDocument = mock(XWikiDeletedDocument.class);
771  1 when(deletedDocument.getDocumentReference()).thenReturn(documentReference);
772  1 when(xwiki.getDeletedDocument(anyLong(), eq(xcontext))).thenReturn(deletedDocument);
773   
774  1 when(xwiki.exists(documentReference, xcontext)).thenReturn(false);
775  1 when(xwiki.getRecycleBinStore()).thenReturn(recycleBin);
776   
777  1 when(recycleBin.getNumberOfDeletedDocuments(any())).thenReturn((long)nbDocs);
778  1 when(recycleBin.getAllDeletedDocumentsIds(eq(this.xcontext), anyInt())).thenReturn(new Long[]{
779    1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L
780    }).thenReturn(new Long[]{
781    11L, 12L
782    });
783  1 when(request.isCheckRights()).thenReturn(false);
784  1 when(request.isCheckAuthorRights()).thenReturn(false);
785   
786  1 assertTrue(this.modelBridge.permanentlyDeleteAllDocuments(deleteJob, request));
787  1 verify(this.progressManager).pushLevelProgress(nbDocs, deleteJob);
788  1 verify(this.progressManager, times(12)).startStep(deleteJob);
789  1 verify(this.progressManager, times(12)).endStep(deleteJob);
790  13 for (int i = 1; i <= 12; i++) {
791  12 verify(recycleBin).deleteFromRecycleBin(i, xcontext, true);
792  12 assertLog(i-1, Level.INFO, "Document [{}] has been permanently deleted.", documentReference);
793    }
794    }
795    }