Skip to content

Commit

Permalink
Test media partial form validation, code improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
markusweigelt committed Nov 20, 2023
1 parent 56e25e1 commit 62f06bd
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,15 @@

public class MediaPartialForm implements Serializable {

private final DataEditorForm dataEditor;

private final DataEditorForm dataEditorForm;
private Map.Entry<LogicalDivision, MediaPartialView> mediaPartialDivision;
private String title;
private String begin;
private String type;
private String validationErrorMessage;
private String validationError;

MediaPartialForm(DataEditorForm dataEditor) {
this.dataEditor = dataEditor;
MediaPartialForm(DataEditorForm dataEditorForm) {
this.dataEditorForm = dataEditorForm;
}

/**
Expand All @@ -61,7 +60,7 @@ public void clean() {
mediaPartialDivision = null;
title = "";
begin = null;
validationErrorMessage = "";
validationError = "";
Ajax.update("mediaPartialForm");
}

Expand All @@ -70,17 +69,17 @@ public void clean() {
*
* @return The validation error message.
*/
public String getValidationErrorMessage() {
return validationErrorMessage;
public String getValidationError() {
return Helper.getTranslation(validationError);
}

/**
* Check if form has a validation error message.
* Check if form has a validation error.
*
* @return True if validation error is not empty.
*/
public boolean hasValidationErrorMessage() {
return StringUtils.isNotEmpty(validationErrorMessage);
public boolean hasValidationError() {
return StringUtils.isNotEmpty(validationError);
}

/**
Expand Down Expand Up @@ -110,7 +109,7 @@ public void save() {
physicalDivision.getLogicalDivisions().add(logicalDivision);

LinkedList<PhysicalDivision> ancestorsOfPhysicalDivision = MetadataEditor.getAncestorsOfPhysicalDivision(
getMediaSelection().getKey(), dataEditor.getWorkpiece().getPhysicalStructure());
getMediaSelection().getKey(), dataEditorForm.getWorkpiece().getPhysicalStructure());

ancestorsOfPhysicalDivision.getLast().getChildren().add(physicalDivision);

Expand All @@ -122,13 +121,12 @@ public void save() {
convertFormattedTimeToMilliseconds(getMediaDuration()));

try {
dataEditor.refreshStructurePanel();
dataEditorForm.refreshStructurePanel();
} catch (UnknownTreeNodeDataException e) {
Helper.setErrorMessage(e.getMessage());
}

Ajax.update("structureTreeForm", "imagePreviewForm:mediaDetailMediaPartialsContainer",
"imagePreviewForm:thumbnailStripe");
Ajax.update(MediaPartialsPanel.UPDATE_CLIENT_IDENTIFIERS);
PrimeFaces.current().executeScript("PF('addMediaPartialDialog').hide();");
}

Expand Down Expand Up @@ -160,42 +158,42 @@ public void setType(String type) {
this.type = type;
}

private String getMediaDuration() {
return dataEditor.getGalleryPanel().getMediaPartialsPanel().getMediaDuration();
protected String getMediaDuration() {
return dataEditorForm.getGalleryPanel().getMediaPartialsPanel().getMediaDuration();
}
private Pair<PhysicalDivision, LogicalDivision> getMediaSelection() {
return dataEditor.getGalleryPanel().getMediaPartialsPanel().getMediaSelection();

protected Pair<PhysicalDivision, LogicalDivision> getMediaSelection() {
return dataEditorForm.getGalleryPanel().getMediaPartialsPanel().getMediaSelection();
}

private boolean valid() {
validationErrorMessage = "";
protected boolean valid() {
validationError = "";
if (Objects.isNull(getMediaSelection())) {
validationErrorMessage = Helper.getTranslation("mediaPartialFormNoMedium");
validationError = "mediaPartialFormNoMedium";
return false;
}
validationErrorMessage = dataEditor.getGalleryPanel().getMediaPartialsPanel().validateDuration();
if (Objects.nonNull(validationErrorMessage)) {
validationError = dataEditorForm.getGalleryPanel().getMediaPartialsPanel().validateDuration();
if (Objects.nonNull(validationError)) {
return false;
}
if (StringUtils.isEmpty(getBegin())) {
validationErrorMessage = Helper.getTranslation("mediaPartialFormStartEmpty");
validationError = "mediaPartialFormStartEmpty";
return false;
}
if (!Pattern.compile(MediaPartialsPanel.FORMATTED_TIME_REGEX).matcher(getBegin()).matches()) {
validationErrorMessage = Helper.getTranslation("mediaPartialFormStartWrongTimeFormat");
validationError = "mediaPartialFormStartWrongTimeFormat";
return false;
}
if (convertFormattedTimeToMilliseconds(getBegin()) >= convertFormattedTimeToMilliseconds(getMediaDuration())) {
validationErrorMessage = Helper.getTranslation("mediaPartialFormStartLessThanMediaDuration");
validationError = "mediaPartialFormStartLessThanMediaDuration";
return false;
}
if (!isEdit() || (isEdit() && !mediaPartialDivision.getValue().getBegin().equals(getBegin()))) {
boolean exists = getMediaSelection().getValue().getChildren().stream().anyMatch(
logicalDivision -> logicalDivision.getViews().getFirst().getPhysicalDivision().getMediaPartialView()
.getBegin().equals(getBegin()));
if (exists) {
validationErrorMessage = Helper.getTranslation("mediaPartialFormStartExists");
validationError = "mediaPartialFormStartExists";
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@
import org.kitodo.production.helper.Helper;
import org.kitodo.production.services.dataeditor.DataEditorService;
import org.kitodo.utils.MediaUtil;


import org.omnifaces.util.Ajax;

public class MediaPartialsPanel implements Serializable {

public static final String FORMATTED_TIME_REGEX = "([0-1]\\d|2[0-3]):[0-5]\\d:[0-5]\\d";
public static final String REQUEST_PARAMETER_MEDIA_DURATION = "mediaDuration";
public static final String[] UPDATE_CLIENT_IDENTIFIERS = {"structureTreeForm",
"imagePreviewForm:mediaDetailMediaPartialsContainer",
"imagePreviewForm:thumbnailStripe"};
private MediaPartialForm mediaPartialForm;
private DataEditorForm dataEditor;
private String mediaDuration;
Expand Down Expand Up @@ -89,16 +91,16 @@ private static void getMediaPartialViewDivisions(Map<LogicalDivision, MediaParti
/**
* Validate the duration of the media.
*
* @return The error message if duration is not valid.
* @return The error if duration is not valid.
*/
public String validateDuration() {
String errorMessage = null;
String error = null;
if (StringUtils.isEmpty(getMediaDuration())) {
errorMessage = Helper.getTranslation("mediaPartialFormMediaDurationEmpty");
error = "mediaPartialFormMediaDurationEmpty";
} else if (!Pattern.compile(MediaPartialsPanel.FORMATTED_TIME_REGEX).matcher(getMediaDuration()).matches()) {
errorMessage = Helper.getTranslation("mediaPartialFormMediaDurationWrongTimeFormat");
error = "mediaPartialFormMediaDurationWrongTimeFormat";
}
return errorMessage;
return error;
}

/**
Expand All @@ -107,9 +109,9 @@ public String validateDuration() {
* @param mediaViewDivision to delete
*/
public void deleteMediaViewDivision(Map.Entry<LogicalDivision, MediaPartialView> mediaViewDivision) {
String errorMessage = validateDuration();
if (Objects.nonNull(errorMessage)) {
Helper.setErrorMessage(errorMessage);
String error = validateDuration();
if (Objects.nonNull(error)) {
Helper.setErrorMessage(Helper.getTranslation(error));
return;
}

Expand All @@ -121,6 +123,8 @@ public void deleteMediaViewDivision(Map.Entry<LogicalDivision, MediaPartialView>
generateExtentAndSortMediaPartials(getMediaSelection().getValue().getChildren(),
convertFormattedTimeToMilliseconds(getMediaDuration()));
}

Ajax.update(UPDATE_CLIENT_IDENTIFIERS);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class AudioWaveform {

this.#wavesurfer = WaveSurfer.create({
container: document.getElementById(waveContainer.getAttribute("id")),
height: 100,
height: 250,
waveColor: "#f3f3f3",
progressColor: "#ff4e00",
cursorColor: "#ffffff",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* (c) Kitodo. Key to digital objects e. V. <[email protected]>
*
* This file is part of the Kitodo project.
*
* It is licensed under GNU General Public License version 3 or later.
*
* For the full copyright and license information, please read the
* GPL3-License.txt file that was distributed with this source code.
*/

package org.kitodo.production.forms.dataeditor;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.junit.Assert;
import org.junit.Test;
import org.kitodo.api.dataformat.LogicalDivision;
import org.kitodo.api.dataformat.MediaPartialView;
import org.kitodo.api.dataformat.PhysicalDivision;
import org.kitodo.api.dataformat.View;

import java.lang.reflect.Field;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

public class MediaPartialFormTest {

@Test
public void testValidation() throws NoSuchFieldException, IllegalAccessException {
DataEditorForm dataEditorForm = mock(DataEditorForm.class);
GalleryPanel galleryPanel = mock(GalleryPanel.class);
MediaPartialsPanel mediaPartialsPanel = spy(new MediaPartialsPanel(dataEditorForm));
when(dataEditorForm.getGalleryPanel()).thenReturn(galleryPanel);
when(galleryPanel.getMediaPartialsPanel()).thenReturn(mediaPartialsPanel);

MediaPartialForm mediaPartialForm = spy(new MediaPartialForm(dataEditorForm));

Assert.assertFalse(mediaPartialForm.valid());
Assert.assertEquals("mediaPartialFormNoMedium", getValidationError(mediaPartialForm));

View view = mock(View.class);
PhysicalDivision physicalDivision = spy(PhysicalDivision.class);
String existingMediaPartialBegin = "00:00:30";
physicalDivision.setMediaPartialView(new MediaPartialView(existingMediaPartialBegin));
when(view.getPhysicalDivision()).thenReturn(physicalDivision);

LogicalDivision childLogicalDivision = spy(LogicalDivision.class);
childLogicalDivision.getViews().add(view);
LogicalDivision logicalDivision = new LogicalDivision();
logicalDivision.getChildren().add(childLogicalDivision);

when(mediaPartialForm.getMediaSelection()).thenReturn(new ImmutablePair<>(null, logicalDivision));
Assert.assertFalse(mediaPartialForm.valid());
Assert.assertEquals("mediaPartialFormMediaDurationEmpty", getValidationError(mediaPartialForm));

when(mediaPartialsPanel.getMediaDuration()).thenReturn("12345");
Assert.assertFalse(mediaPartialForm.valid());
Assert.assertEquals("mediaPartialFormMediaDurationWrongTimeFormat", getValidationError(mediaPartialForm));

when(mediaPartialsPanel.getMediaDuration()).thenReturn("00:01:00");
Assert.assertFalse(mediaPartialForm.valid());
Assert.assertEquals("mediaPartialFormStartEmpty", getValidationError(mediaPartialForm));

when(mediaPartialForm.getBegin()).thenReturn("12345");
Assert.assertFalse(mediaPartialForm.valid());
Assert.assertEquals("mediaPartialFormStartWrongTimeFormat", getValidationError(mediaPartialForm));

when(mediaPartialForm.getBegin()).thenReturn("00:02:00");
Assert.assertFalse(mediaPartialForm.valid());
Assert.assertEquals("mediaPartialFormStartLessThanMediaDuration", getValidationError(mediaPartialForm));

when(mediaPartialForm.getBegin()).thenReturn(existingMediaPartialBegin);
Assert.assertFalse(mediaPartialForm.valid());
Assert.assertEquals("mediaPartialFormStartExists", getValidationError(mediaPartialForm));

when(mediaPartialForm.getBegin()).thenReturn("00:00:45");
Assert.assertTrue(mediaPartialForm.valid());
}

private static String getValidationError(MediaPartialForm mediaPartialForm)
throws NoSuchFieldException, IllegalAccessException {
Field validationErrorField = mediaPartialForm.getClass().getDeclaredField("validationError");
validationErrorField.setAccessible(true);
String validationError = (String) validationErrorField.get(mediaPartialForm);
return validationError;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* (c) Kitodo. Key to digital objects e. V. <[email protected]>
*
* This file is part of the Kitodo project.
*
* It is licensed under GNU General Public License version 3 or later.
*
* For the full copyright and license information, please read the
* GPL3-License.txt file that was distributed with this source code.
*/

package org.kitodo.production.forms.dataeditor;

import org.junit.Assert;
import org.junit.Test;
import org.kitodo.DummyRulesetManagement;
import org.kitodo.api.dataformat.LogicalDivision;
import org.kitodo.api.dataformat.mets.LinkedMetsResource;
import org.kitodo.data.database.beans.Process;
import org.kitodo.data.database.beans.Template;
import org.kitodo.data.database.beans.Workflow;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URI;

public class MediaPartialPanelTest {

@Test
public void testBuildStructureTreeRecursively() throws Exception {
DataEditorForm dummyDataEditorForm = new DataEditorForm();
Process process = new Process();
Template template = new Template();
template.setWorkflow(new Workflow());
process.setTemplate(template);
dummyDataEditorForm.setProcess(process);
Field ruleset = DataEditorForm.class.getDeclaredField("ruleset");
ruleset.setAccessible(true);
ruleset.set(dummyDataEditorForm, new DummyRulesetManagement());
final StructurePanel underTest = new StructurePanel(dummyDataEditorForm);

LogicalDivision structure = new LogicalDivision();
LinkedMetsResource link = new LinkedMetsResource();
link.setUri(URI.create("database://?process.id=42"));
structure.setLink(link);
TreeNode result = new DefaultTreeNode();

Method buildStructureTreeRecursively = StructurePanel.class.getDeclaredMethod("buildStructureTreeRecursively",
LogicalDivision.class, TreeNode.class);
buildStructureTreeRecursively.setAccessible(true);
buildStructureTreeRecursively.invoke(underTest, structure, result);

Assert.assertTrue(((StructureTreeNode) result.getChildren().get(0).getData()).isLinked());
}

@Test
public void preventNullPointerExceptionInIsSeparateMediaOnNotFullInitializedDataEditorForm() {
DataEditorForm dummyDataEditorForm = new DataEditorForm();
final StructurePanel underTest = new StructurePanel(dummyDataEditorForm);
Assert.assertFalse(underTest.isSeparateMedia());
}
}

0 comments on commit 62f06bd

Please sign in to comment.