This is an automated email from the ASF dual-hosted git repository.
hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new e734a122f0 Issue #2742 : multi-transform unit test tweaks and editor
support (#7573)
e734a122f0 is described below
commit e734a122f0badcdf20bb510e7e5bdf893ec78487
Author: Matt Casters <[email protected]>
AuthorDate: Mon Jul 20 12:45:53 2026 +0200
Issue #2742 : multi-transform unit test tweaks and editor support (#7573)
Apply Bypass/Remove/Include unit-test tweak actions to all selected
transforms, not only the right-clicked one. Rework PipelineUnitTestEditor
into General, Database, Parameters & Variables, and Tweaks tabs so stored
tweaks are visible and editable in metadata.
---
.../apache/hop/testing/gui/TestingGuiPlugin.java | 62 ++++-
.../org/apache/hop/testing/util/DataSetConst.java | 42 ++++
.../hop/ui/testing/PipelineUnitTestEditor.java | 249 +++++++++++++++++----
.../ui/testing/messages/messages_en_US.properties | 7 +
.../hop/testing/gui/TestingGuiPluginTweakTest.java | 140 ++++++++++++
5 files changed, 443 insertions(+), 57 deletions(-)
diff --git
a/plugins/misc/testing/src/main/java/org/apache/hop/testing/gui/TestingGuiPlugin.java
b/plugins/misc/testing/src/main/java/org/apache/hop/testing/gui/TestingGuiPlugin.java
index 28ee451809..7d89ad5f8f 100644
---
a/plugins/misc/testing/src/main/java/org/apache/hop/testing/gui/TestingGuiPlugin.java
+++
b/plugins/misc/testing/src/main/java/org/apache/hop/testing/gui/TestingGuiPlugin.java
@@ -1407,7 +1407,11 @@ public class TestingGuiPlugin {
TransformMeta transformMeta = context.getTransformMeta();
IVariables variables = context.getPipelineGraph().getVariables();
- if (transformMeta == null || pipelineMeta == null) {
+ if (pipelineMeta == null) {
+ return;
+ }
+ List<TransformMeta> targets = resolveTweakTargetTransforms(pipelineMeta,
transformMeta);
+ if (targets.isEmpty()) {
return;
}
if (checkTestPresent(hopGui, context)) {
@@ -1419,12 +1423,10 @@ public class TestingGuiPlugin {
if (unitTest == null) {
return;
}
- PipelineUnitTestTweak unitTestTweak =
unitTest.findTweak(transformMeta.getName());
- if (unitTestTweak != null) {
- unitTest.getTweaks().remove(unitTestTweak);
- }
- if (enable) {
- unitTest.getTweaks().add(new PipelineUnitTestTweak(tweak,
transformMeta.getName()));
+
+ // Apply to all selected transforms (issue #2742), not only the one
right-clicked
+ for (TransformMeta target : targets) {
+ applyTweakToTransform(unitTest, target.getName(), tweak, enable);
}
saveUnitTest(variables, metadataProvider, unitTest, pipelineMeta);
@@ -1439,12 +1441,56 @@ public class TestingGuiPlugin {
BaseMessages.getString(
PKG,
"TestingGuiPlugin.TweakUnitTestTransform.Error.Message",
- transformMeta.getName(),
+ targets.get(0).getName(),
tweak.name()),
exception);
}
}
+ /**
+ * Resolve which transforms a unit-test tweak action should affect. Prefer
the current selection;
+ * if nothing is selected, fall back to the transform that was right-clicked.
+ *
+ * @param pipelineMeta the pipeline containing the selection
+ * @param clickedTransform the transform under the context menu, may be null
+ * @return the transforms to tweak (never null)
+ */
+ static List<TransformMeta> resolveTweakTargetTransforms(
+ PipelineMeta pipelineMeta, TransformMeta clickedTransform) {
+ List<TransformMeta> selected = pipelineMeta.getSelectedTransforms();
+ if (selected != null && !selected.isEmpty()) {
+ return selected;
+ }
+ if (clickedTransform == null) {
+ return Collections.emptyList();
+ }
+ return Collections.singletonList(clickedTransform);
+ }
+
+ /**
+ * Apply or clear a unit-test tweak on a single transform. When enabling,
any existing tweak on
+ * the transform is replaced. When disabling, only a tweak of the requested
type is removed so a
+ * multi-select action does not wipe unrelated tweaks.
+ *
+ * @param unitTest the active unit test
+ * @param transformName name of the transform to tweak
+ * @param tweak the tweak type
+ * @param enable true to set the tweak, false to clear a matching tweak
+ */
+ static void applyTweakToTransform(
+ PipelineUnitTest unitTest, String transformName, PipelineTweak tweak,
boolean enable) {
+ PipelineUnitTestTweak existing = unitTest.findTweak(transformName);
+ if (existing != null) {
+ if (!enable && existing.getTweak() != tweak) {
+ return;
+ }
+ unitTest.getTweaks().remove(existing);
+ }
+ if (enable) {
+ unitTest.getTweaks().add(new PipelineUnitTestTweak(tweak,
transformName));
+ }
+ }
+
/** List all unit tests which are defined And allow the user to select one */
public RowMetaAndData selectUnitTestFromAllTests() {
HopGui hopGui = HopGui.getInstance();
diff --git
a/plugins/misc/testing/src/main/java/org/apache/hop/testing/util/DataSetConst.java
b/plugins/misc/testing/src/main/java/org/apache/hop/testing/util/DataSetConst.java
index 4340b18954..e2901c36ef 100644
---
a/plugins/misc/testing/src/main/java/org/apache/hop/testing/util/DataSetConst.java
+++
b/plugins/misc/testing/src/main/java/org/apache/hop/testing/util/DataSetConst.java
@@ -37,6 +37,7 @@ import org.apache.hop.metadata.api.IHopMetadataProvider;
import org.apache.hop.pipeline.PipelineMeta;
import org.apache.hop.pipeline.engine.IPipelineEngine;
import org.apache.hop.testing.DataSet;
+import org.apache.hop.testing.PipelineTweak;
import org.apache.hop.testing.PipelineUnitTest;
import org.apache.hop.testing.PipelineUnitTestFieldMapping;
import org.apache.hop.testing.PipelineUnitTestSetLocation;
@@ -522,4 +523,45 @@ public class DataSetConst {
public static String[] getTestTypeDescriptions() {
return testTypeDesc;
}
+
+ /**
+ * Get the localized description for a pipeline unit-test tweak.
+ *
+ * @param tweak the tweak type
+ * @return description for dialogs/editors
+ */
+ public static String getTweakDescription(PipelineTweak tweak) {
+ int index = 0; // NONE
+ if (tweak != null) {
+ PipelineTweak[] tweaks = PipelineTweak.values();
+ for (int i = 0; i < tweaks.length; i++) {
+ if (tweaks[i] == tweak) {
+ index = i;
+ break;
+ }
+ }
+ }
+ return tweakDesc[index];
+ }
+
+ /**
+ * Get the PipelineTweak for a description (from the dialog).
+ *
+ * @param tweakDescription the description to look for
+ * @return the tweak type or NONE if nothing matched
+ */
+ public static PipelineTweak getTweakForDescription(String tweakDescription) {
+ if (StringUtils.isEmpty(tweakDescription)) {
+ return PipelineTweak.NONE;
+ }
+ int index = Const.indexOfString(tweakDescription, tweakDesc);
+ if (index < 0) {
+ return PipelineTweak.NONE;
+ }
+ return PipelineTweak.values()[index];
+ }
+
+ public static String[] getTweakDescriptions() {
+ return tweakDesc;
+ }
}
diff --git
a/plugins/misc/testing/src/main/java/org/apache/hop/ui/testing/PipelineUnitTestEditor.java
b/plugins/misc/testing/src/main/java/org/apache/hop/ui/testing/PipelineUnitTestEditor.java
index f39d206009..4fcb94271d 100644
---
a/plugins/misc/testing/src/main/java/org/apache/hop/ui/testing/PipelineUnitTestEditor.java
+++
b/plugins/misc/testing/src/main/java/org/apache/hop/ui/testing/PipelineUnitTestEditor.java
@@ -21,17 +21,21 @@ import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.hop.core.Const;
+import org.apache.hop.core.Props;
import org.apache.hop.core.database.DatabaseMeta;
import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.logging.LogChannel;
import org.apache.hop.i18n.BaseMessages;
import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.testing.PipelineTweak;
import org.apache.hop.testing.PipelineUnitTest;
import org.apache.hop.testing.PipelineUnitTestDatabaseReplacement;
+import org.apache.hop.testing.PipelineUnitTestTweak;
import org.apache.hop.testing.VariableValue;
import org.apache.hop.testing.util.DataSetConst;
import org.apache.hop.ui.core.PropsUi;
import org.apache.hop.ui.core.dialog.BaseDialog;
+import org.apache.hop.ui.core.gui.GuiResource;
import org.apache.hop.ui.core.metadata.MetadataEditor;
import org.apache.hop.ui.core.metadata.MetadataManager;
import org.apache.hop.ui.core.widget.ColumnInfo;
@@ -39,9 +43,12 @@ import org.apache.hop.ui.core.widget.TableView;
import org.apache.hop.ui.core.widget.TextVar;
import org.apache.hop.ui.hopgui.HopGui;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
@@ -64,6 +71,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
private Button wAutoOpen;
private TableView wDbReplacements;
private TableView wVariableValues;
+ private TableView wTweaks;
private final PropsUi props;
@@ -82,12 +90,59 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
PipelineUnitTest pipelineUnitTest = this.getMetadata();
+ int margin = PropsUi.getMargin();
+
+ CTabFolder wTabFolder = new CTabFolder(parent, SWT.BORDER);
+ PropsUi.setLook(wTabFolder, Props.WIDGET_STYLE_TAB);
+ FormData fdTabFolder = new FormData();
+ fdTabFolder.left = new FormAttachment(0, 0);
+ fdTabFolder.top = new FormAttachment(0, 0);
+ fdTabFolder.right = new FormAttachment(100, 0);
+ fdTabFolder.bottom = new FormAttachment(100, -margin);
+ wTabFolder.setLayoutData(fdTabFolder);
+
+ createGeneralTab(wTabFolder);
+ createDatabaseTab(wTabFolder, pipelineUnitTest);
+ createVariablesTab(wTabFolder, pipelineUnitTest);
+ createTweaksTab(wTabFolder, pipelineUnitTest);
+
+ wTabFolder.setSelection(0);
+
+ setWidgetsContent();
+
+ // Add listener to detect change after loading data
+ Listener listener = e -> setChanged();
+ ModifyListener modifyListener = e -> setChanged();
+ wName.addListener(SWT.Modify, listener);
+ wDescription.addListener(SWT.Modify, listener);
+ wTestType.addListener(SWT.Modify, listener);
+ wPipelineFilename.addListener(SWT.Modify, listener);
+ wFilename.addListener(SWT.Modify, listener);
+ wBasePath.addListener(SWT.Modify, listener);
+ wAutoOpen.addListener(SWT.Selection, listener);
+ wDbReplacements.addModifyListener(modifyListener);
+ wVariableValues.addModifyListener(modifyListener);
+ wTweaks.addModifyListener(modifyListener);
+ }
+
+ private void createGeneralTab(CTabFolder wTabFolder) {
int middle = props.getMiddlePct();
int margin = PropsUi.getMargin();
+ CTabItem wGeneralTab = new CTabItem(wTabFolder, SWT.NONE);
+ wGeneralTab.setFont(GuiResource.getInstance().getFontDefault());
+ wGeneralTab.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.Tab.General"));
+
+ Composite wGeneralComp = new Composite(wTabFolder, SWT.NONE);
+ PropsUi.setLook(wGeneralComp);
+ FormLayout generalLayout = new FormLayout();
+ generalLayout.marginWidth = PropsUi.getFormMargin();
+ generalLayout.marginHeight = PropsUi.getFormMargin();
+ wGeneralComp.setLayout(generalLayout);
+
// The name of the unit test...
//
- Label wlName = new Label(parent, SWT.RIGHT);
+ Label wlName = new Label(wGeneralComp, SWT.RIGHT);
PropsUi.setLook(wlName);
wlName.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.Name.Label"));
FormData fdlName = new FormData();
@@ -95,7 +150,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
fdlName.left = new FormAttachment(0, 0);
fdlName.right = new FormAttachment(middle, -margin);
wlName.setLayoutData(fdlName);
- wName = new Text(parent, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ wName = new Text(wGeneralComp, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
PropsUi.setLook(wName);
FormData fdName = new FormData();
fdName.top = new FormAttachment(0, margin);
@@ -106,7 +161,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
// The description of the test...
//
- Label wlDescription = new Label(parent, SWT.RIGHT);
+ Label wlDescription = new Label(wGeneralComp, SWT.RIGHT);
PropsUi.setLook(wlDescription);
wlDescription.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.Description.Label"));
FormData fdlDescription = new FormData();
@@ -114,7 +169,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
fdlDescription.left = new FormAttachment(0, 0);
fdlDescription.right = new FormAttachment(middle, -margin);
wlDescription.setLayoutData(fdlDescription);
- wDescription = new Text(parent, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ wDescription = new Text(wGeneralComp, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
PropsUi.setLook(wDescription);
FormData fdDescription = new FormData();
fdDescription.top = new FormAttachment(lastControl, margin);
@@ -125,7 +180,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
// The type of test...
//
- Label wlTestType = new Label(parent, SWT.RIGHT);
+ Label wlTestType = new Label(wGeneralComp, SWT.RIGHT);
PropsUi.setLook(wlTestType);
wlTestType.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.TestType.Label"));
FormData fdlTestType = new FormData();
@@ -133,7 +188,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
fdlTestType.left = new FormAttachment(0, 0);
fdlTestType.right = new FormAttachment(middle, -margin);
wlTestType.setLayoutData(fdlTestType);
- wTestType = new Combo(parent, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ wTestType = new Combo(wGeneralComp, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
PropsUi.setLook(wTestType);
FormData fdTestType = new FormData();
fdTestType.top = new FormAttachment(lastControl, margin);
@@ -145,7 +200,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
// The filename of the pipeline to test
//
- Label wlPipelineFilename = new Label(parent, SWT.RIGHT);
+ Label wlPipelineFilename = new Label(wGeneralComp, SWT.RIGHT);
PropsUi.setLook(wlPipelineFilename);
wlPipelineFilename.setText(
BaseMessages.getString(PKG,
"PipelineUnitTestDialog.PipelineFilename.Label"));
@@ -155,7 +210,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
fdlPipelineFilename.right = new FormAttachment(middle, -margin);
wlPipelineFilename.setLayoutData(fdlPipelineFilename);
- Button wbPipelineFilename = new Button(parent, SWT.PUSH);
+ Button wbPipelineFilename = new Button(wGeneralComp, SWT.PUSH);
PropsUi.setLook(wbPipelineFilename);
wbPipelineFilename.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.Button.Browse"));
FormData fdbPipelineFilename = new FormData();
@@ -163,7 +218,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
fdbPipelineFilename.top = new FormAttachment(lastControl, margin);
wbPipelineFilename.setLayoutData(fdbPipelineFilename);
wbPipelineFilename.addListener(SWT.Selection,
this::browsePipelineFilename);
- wPipelineFilename = new Text(parent, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ wPipelineFilename = new Text(wGeneralComp, SWT.SINGLE | SWT.LEFT |
SWT.BORDER);
PropsUi.setLook(wPipelineFilename);
FormData fdPipelineFilename = new FormData();
fdPipelineFilename.top = new FormAttachment(lastControl, margin);
@@ -174,7 +229,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
// The optional filename of the test result...
//
- Label wlFilename = new Label(parent, SWT.RIGHT);
+ Label wlFilename = new Label(wGeneralComp, SWT.RIGHT);
PropsUi.setLook(wlFilename);
wlFilename.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.Filename.Label"));
FormData fdlFilename = new FormData();
@@ -182,7 +237,8 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
fdlFilename.left = new FormAttachment(0, 0);
fdlFilename.right = new FormAttachment(middle, -margin);
wlFilename.setLayoutData(fdlFilename);
- wFilename = new TextVar(manager.getVariables(), parent, SWT.SINGLE |
SWT.LEFT | SWT.BORDER);
+ wFilename =
+ new TextVar(manager.getVariables(), wGeneralComp, SWT.SINGLE |
SWT.LEFT | SWT.BORDER);
PropsUi.setLook(wFilename);
FormData fdFilename = new FormData();
fdFilename.top = new FormAttachment(lastControl, margin);
@@ -193,7 +249,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
// The base path for relative test path resolution
//
- Label wlBasePath = new Label(parent, SWT.RIGHT);
+ Label wlBasePath = new Label(wGeneralComp, SWT.RIGHT);
PropsUi.setLook(wlBasePath);
wlBasePath.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.BasePath.Label"));
FormData fdlBasePath = new FormData();
@@ -202,7 +258,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
fdlBasePath.right = new FormAttachment(middle, -margin);
wlBasePath.setLayoutData(fdlBasePath);
- Button wbBasePath = new Button(parent, SWT.PUSH);
+ Button wbBasePath = new Button(wGeneralComp, SWT.PUSH);
PropsUi.setLook(wbBasePath);
wbBasePath.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.Button.Browse"));
FormData fdbBasePath = new FormData();
@@ -211,7 +267,8 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
wbBasePath.setLayoutData(fdbBasePath);
wbBasePath.addListener(SWT.Selection, this::browseTestPathDir);
- wBasePath = new TextVar(manager.getVariables(), parent, SWT.SINGLE |
SWT.LEFT | SWT.BORDER);
+ wBasePath =
+ new TextVar(manager.getVariables(), wGeneralComp, SWT.SINGLE |
SWT.LEFT | SWT.BORDER);
PropsUi.setLook(wBasePath);
FormData fdBasePath = new FormData();
fdBasePath.top = new FormAttachment(lastControl, margin);
@@ -222,7 +279,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
// Auto-open checkbox
//
- Label wlAutoOpen = new Label(parent, SWT.RIGHT);
+ Label wlAutoOpen = new Label(wGeneralComp, SWT.RIGHT);
PropsUi.setLook(wlAutoOpen);
wlAutoOpen.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.AutoOpen.Label"));
FormData fdlAutoOpen = new FormData();
@@ -230,28 +287,40 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
fdlAutoOpen.left = new FormAttachment(0, 0);
fdlAutoOpen.right = new FormAttachment(middle, -margin);
wlAutoOpen.setLayoutData(fdlAutoOpen);
- wAutoOpen = new Button(parent, SWT.CHECK);
+ wAutoOpen = new Button(wGeneralComp, SWT.CHECK);
PropsUi.setLook(wAutoOpen);
FormData fdAutoOpen = new FormData();
fdAutoOpen.top = new FormAttachment(wlAutoOpen, 0, SWT.CENTER);
fdAutoOpen.left = new FormAttachment(middle, 0);
wAutoOpen.setLayoutData(fdAutoOpen);
- lastControl = wAutoOpen;
- // The list of database replacements in the unit test pipeline
- //
- Label wlDbReplacements = new Label(parent, SWT.NONE);
+ wGeneralComp.layout();
+ wGeneralTab.setControl(wGeneralComp);
+ }
+
+ private void createDatabaseTab(CTabFolder wTabFolder, PipelineUnitTest
pipelineUnitTest) {
+ int margin = PropsUi.getMargin();
+
+ CTabItem wDatabaseTab = new CTabItem(wTabFolder, SWT.NONE);
+ wDatabaseTab.setFont(GuiResource.getInstance().getFontDefault());
+ wDatabaseTab.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.Tab.Database"));
+
+ Composite wDatabaseComp = new Composite(wTabFolder, SWT.NONE);
+ PropsUi.setLook(wDatabaseComp);
+ FormLayout databaseLayout = new FormLayout();
+ databaseLayout.marginWidth = PropsUi.getFormMargin();
+ databaseLayout.marginHeight = PropsUi.getFormMargin();
+ wDatabaseComp.setLayout(databaseLayout);
+
+ Label wlDbReplacements = new Label(wDatabaseComp, SWT.NONE);
wlDbReplacements.setText(
BaseMessages.getString(PKG,
"PipelineUnitTestDialog.DbReplacements.Label"));
PropsUi.setLook(wlDbReplacements);
FormData fdlDbReplacements = new FormData();
fdlDbReplacements.left = new FormAttachment(0, 0);
- fdlDbReplacements.top = new FormAttachment(lastControl, 2 * margin);
+ fdlDbReplacements.top = new FormAttachment(0, 0);
wlDbReplacements.setLayoutData(fdlDbReplacements);
- lastControl = wlDbReplacements;
- // the database replacements
- //
List<String> dbNames;
try {
dbNames =
metadataProvider.getSerializer(DatabaseMeta.class).listObjectNames();
@@ -281,30 +350,46 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
wDbReplacements =
new TableView(
manager.getVariables(),
- parent,
+ wDatabaseComp,
SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.V_SCROLL |
SWT.H_SCROLL,
columns,
- pipelineUnitTest.getTweaks().size(),
+ pipelineUnitTest.getDatabaseReplacements().size(),
null,
props);
FormData fdDbReplacements = new FormData();
fdDbReplacements.left = new FormAttachment(0, 0);
- fdDbReplacements.top = new FormAttachment(lastControl, margin);
+ fdDbReplacements.top = new FormAttachment(wlDbReplacements, margin);
fdDbReplacements.right = new FormAttachment(100, 0);
- fdDbReplacements.bottom = new FormAttachment(50, -margin);
+ fdDbReplacements.bottom = new FormAttachment(100, 0);
wDbReplacements.setLayoutData(fdDbReplacements);
- lastControl = wDbReplacements;
- Label wlVariableValues = new Label(parent, SWT.NONE);
+ wDatabaseComp.layout();
+ wDatabaseTab.setControl(wDatabaseComp);
+ }
+
+ private void createVariablesTab(CTabFolder wTabFolder, PipelineUnitTest
pipelineUnitTest) {
+ int margin = PropsUi.getMargin();
+
+ CTabItem wVariablesTab = new CTabItem(wTabFolder, SWT.NONE);
+ wVariablesTab.setFont(GuiResource.getInstance().getFontDefault());
+ wVariablesTab.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.Tab.Variables"));
+
+ Composite wVariablesComp = new Composite(wTabFolder, SWT.NONE);
+ PropsUi.setLook(wVariablesComp);
+ FormLayout variablesLayout = new FormLayout();
+ variablesLayout.marginWidth = PropsUi.getFormMargin();
+ variablesLayout.marginHeight = PropsUi.getFormMargin();
+ wVariablesComp.setLayout(variablesLayout);
+
+ Label wlVariableValues = new Label(wVariablesComp, SWT.NONE);
wlVariableValues.setText(
BaseMessages.getString(PKG,
"PipelineUnitTestDialog.VariableValues.Label"));
PropsUi.setLook(wlVariableValues);
FormData fdlVariableValues = new FormData();
fdlVariableValues.left = new FormAttachment(0, 0);
- fdlVariableValues.top = new FormAttachment(lastControl, 2 * margin);
+ fdlVariableValues.top = new FormAttachment(0, 0);
wlVariableValues.setLayoutData(fdlVariableValues);
- lastControl = wlVariableValues;
ColumnInfo[] varValColumns =
new ColumnInfo[] {
@@ -325,7 +410,7 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
wVariableValues =
new TableView(
manager.getVariables(),
- parent,
+ wVariablesComp,
SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.V_SCROLL |
SWT.H_SCROLL,
varValColumns,
pipelineUnitTest.getVariableValues().size(),
@@ -334,26 +419,70 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
FormData fdVariableValues = new FormData();
fdVariableValues.left = new FormAttachment(0, 0);
- fdVariableValues.top = new FormAttachment(lastControl, margin);
+ fdVariableValues.top = new FormAttachment(wlVariableValues, margin);
fdVariableValues.right = new FormAttachment(100, 0);
- fdVariableValues.bottom = new FormAttachment(100, -2 * margin);
+ fdVariableValues.bottom = new FormAttachment(100, 0);
wVariableValues.setLayoutData(fdVariableValues);
- lastControl = wVariableValues;
- setWidgetsContent();
+ wVariablesComp.layout();
+ wVariablesTab.setControl(wVariablesComp);
+ }
- // Add listener to detect change after loading data
- Listener listener = e -> setChanged();
- ModifyListener modifyListener = e -> setChanged();
- wName.addListener(SWT.Modify, listener);
- wDescription.addListener(SWT.Modify, listener);
- wTestType.addListener(SWT.Modify, listener);
- wPipelineFilename.addListener(SWT.Modify, listener);
- wFilename.addListener(SWT.Modify, listener);
- wBasePath.addListener(SWT.Modify, listener);
- wAutoOpen.addListener(SWT.Selection, listener);
- wDbReplacements.addModifyListener(modifyListener);
- wVariableValues.addModifyListener(modifyListener);
+ private void createTweaksTab(CTabFolder wTabFolder, PipelineUnitTest
pipelineUnitTest) {
+ int margin = PropsUi.getMargin();
+
+ CTabItem wTweaksTab = new CTabItem(wTabFolder, SWT.NONE);
+ wTweaksTab.setFont(GuiResource.getInstance().getFontDefault());
+ wTweaksTab.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.Tab.Tweaks"));
+
+ Composite wTweaksComp = new Composite(wTabFolder, SWT.NONE);
+ PropsUi.setLook(wTweaksComp);
+ FormLayout tweaksLayout = new FormLayout();
+ tweaksLayout.marginWidth = PropsUi.getFormMargin();
+ tweaksLayout.marginHeight = PropsUi.getFormMargin();
+ wTweaksComp.setLayout(tweaksLayout);
+
+ Label wlTweaks = new Label(wTweaksComp, SWT.NONE);
+ wlTweaks.setText(BaseMessages.getString(PKG,
"PipelineUnitTestDialog.Tweaks.Label"));
+ PropsUi.setLook(wlTweaks);
+ FormData fdlTweaks = new FormData();
+ fdlTweaks.left = new FormAttachment(0, 0);
+ fdlTweaks.top = new FormAttachment(0, 0);
+ wlTweaks.setLayoutData(fdlTweaks);
+
+ ColumnInfo[] tweakColumns =
+ new ColumnInfo[] {
+ new ColumnInfo(
+ BaseMessages.getString(PKG,
"PipelineUnitTestDialog.Tweaks.ColumnInfo.Tweak"),
+ ColumnInfo.COLUMN_TYPE_CCOMBO,
+ DataSetConst.getTweakDescriptions(),
+ false),
+ new ColumnInfo(
+ BaseMessages.getString(PKG,
"PipelineUnitTestDialog.Tweaks.ColumnInfo.TransformName"),
+ ColumnInfo.COLUMN_TYPE_TEXT,
+ false),
+ };
+ tweakColumns[1].setUsingVariables(true);
+
+ wTweaks =
+ new TableView(
+ manager.getVariables(),
+ wTweaksComp,
+ SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.V_SCROLL |
SWT.H_SCROLL,
+ tweakColumns,
+ pipelineUnitTest.getTweaks().size(),
+ null,
+ props);
+
+ FormData fdTweaks = new FormData();
+ fdTweaks.left = new FormAttachment(0, 0);
+ fdTweaks.top = new FormAttachment(wlTweaks, margin);
+ fdTweaks.right = new FormAttachment(100, 0);
+ fdTweaks.bottom = new FormAttachment(100, 0);
+ wTweaks.setLayoutData(fdTweaks);
+
+ wTweaksComp.layout();
+ wTweaksTab.setControl(wTweaksComp);
}
private void browsePipelineFilename(Event event) {
@@ -416,8 +545,18 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
wVariableValues.setText(Const.NVL(variableValue.getValue(), ""), 2, i);
}
+ for (int i = 0; i < pipelineUnitTest.getTweaks().size(); i++) {
+ PipelineUnitTestTweak tweak = pipelineUnitTest.getTweaks().get(i);
+ wTweaks.setText(DataSetConst.getTweakDescription(tweak.getTweak()), 1,
i);
+ wTweaks.setText(Const.NVL(tweak.getTransformName(), ""), 2, i);
+ }
+
wDbReplacements.removeEmptyRows();
wDbReplacements.setRowNums();
+ wVariableValues.removeEmptyRows();
+ wVariableValues.setRowNums();
+ wTweaks.removeEmptyRows();
+ wTweaks.setRowNums();
}
@Override
@@ -450,5 +589,17 @@ public class PipelineUnitTestEditor extends
MetadataEditor<PipelineUnitTest> {
VariableValue variableValue = new VariableValue(key, value);
test.getVariableValues().add(variableValue);
}
+
+ test.getTweaks().clear();
+ int nrTweaks = wTweaks.nrNonEmpty();
+ for (int i = 0; i < nrTweaks; i++) {
+ TableItem item = wTweaks.getNonEmpty(i);
+ PipelineTweak tweakType =
DataSetConst.getTweakForDescription(item.getText(1));
+ String transformName = item.getText(2);
+ if (StringUtils.isBlank(transformName) || tweakType ==
PipelineTweak.NONE) {
+ continue;
+ }
+ test.getTweaks().add(new PipelineUnitTestTweak(tweakType,
transformName));
+ }
}
}
diff --git
a/plugins/misc/testing/src/main/resources/org/apache/hop/ui/testing/messages/messages_en_US.properties
b/plugins/misc/testing/src/main/resources/org/apache/hop/ui/testing/messages/messages_en_US.properties
index a47835e20f..7304fbe298 100644
---
a/plugins/misc/testing/src/main/resources/org/apache/hop/ui/testing/messages/messages_en_US.properties
+++
b/plugins/misc/testing/src/main/resources/org/apache/hop/ui/testing/messages/messages_en_US.properties
@@ -50,7 +50,14 @@ PipelineUnitTestDialog.Description.Label=Description
PipelineUnitTestDialog.Filename.Label=Test pipeline filename (Optional)
PipelineUnitTestDialog.Name.Label=Name
PipelineUnitTestDialog.PipelineFilename.Label=The pipeline to test
+PipelineUnitTestDialog.Tab.Database=Database
+PipelineUnitTestDialog.Tab.General=General
+PipelineUnitTestDialog.Tab.Tweaks=Tweaks
+PipelineUnitTestDialog.Tab.Variables=Parameters & Variables
PipelineUnitTestDialog.TestType.Label=Type of test
+PipelineUnitTestDialog.Tweaks.ColumnInfo.TransformName=Transform name
+PipelineUnitTestDialog.Tweaks.ColumnInfo.Tweak=Tweak
+PipelineUnitTestDialog.Tweaks.Label=Transform tweaks applied when this unit
test runs:
PipelineUnitTestDialog.VariableValues.ColumnInfo.VariableName=Name
PipelineUnitTestDialog.VariableValues.ColumnInfo.VariableValue=Value
PipelineUnitTestDialog.VariableValues.Label=Parameters and variables
diff --git
a/plugins/misc/testing/src/test/java/org/apache/hop/testing/gui/TestingGuiPluginTweakTest.java
b/plugins/misc/testing/src/test/java/org/apache/hop/testing/gui/TestingGuiPluginTweakTest.java
new file mode 100644
index 0000000000..33f0136f88
--- /dev/null
+++
b/plugins/misc/testing/src/test/java/org/apache/hop/testing/gui/TestingGuiPluginTweakTest.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.testing.gui;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.List;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.transform.TransformMeta;
+import org.apache.hop.testing.PipelineTweak;
+import org.apache.hop.testing.PipelineUnitTest;
+import org.apache.hop.testing.PipelineUnitTestTweak;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Unit tests for multi-transform unit-test tweak application (issue #2742).
Covers pure helpers in
+ * {@link TestingGuiPlugin} that do not require a HopGui instance.
+ */
+class TestingGuiPluginTweakTest {
+
+ @Test
+ void resolveTargetsFallsBackToClickedWhenNothingSelected() {
+ PipelineMeta pipelineMeta = new PipelineMeta();
+ TransformMeta a = transform("A", false);
+ TransformMeta b = transform("B", false);
+ pipelineMeta.addTransform(a);
+ pipelineMeta.addTransform(b);
+
+ List<TransformMeta> targets =
TestingGuiPlugin.resolveTweakTargetTransforms(pipelineMeta, b);
+
+ assertEquals(1, targets.size());
+ assertSame(b, targets.get(0));
+ }
+
+ @Test
+ void resolveTargetsUsesSelectionWhenPresent() {
+ PipelineMeta pipelineMeta = new PipelineMeta();
+ TransformMeta a = transform("A", true);
+ TransformMeta b = transform("B", true);
+ TransformMeta c = transform("C", false);
+ pipelineMeta.addTransform(a);
+ pipelineMeta.addTransform(b);
+ pipelineMeta.addTransform(c);
+
+ List<TransformMeta> targets =
TestingGuiPlugin.resolveTweakTargetTransforms(pipelineMeta, c);
+
+ assertEquals(2, targets.size());
+ assertTrue(targets.contains(a));
+ assertTrue(targets.contains(b));
+ }
+
+ @Test
+ void resolveTargetsEmptyWhenNoSelectionAndNoClick() {
+ PipelineMeta pipelineMeta = new PipelineMeta();
+ pipelineMeta.addTransform(transform("A", false));
+
+ List<TransformMeta> targets =
TestingGuiPlugin.resolveTweakTargetTransforms(pipelineMeta, null);
+
+ assertTrue(targets.isEmpty());
+ }
+
+ @Test
+ void applyTweakEnableAddsBypass() {
+ PipelineUnitTest unitTest = new PipelineUnitTest();
+
+ TestingGuiPlugin.applyTweakToTransform(unitTest, "A",
PipelineTweak.BYPASS_TRANSFORM, true);
+
+ PipelineUnitTestTweak tweak = unitTest.findTweak("A");
+ assertEquals(PipelineTweak.BYPASS_TRANSFORM, tweak.getTweak());
+ assertEquals("A", tweak.getTransformName());
+ }
+
+ @Test
+ void applyTweakEnableReplacesExistingDifferentTweak() {
+ PipelineUnitTest unitTest = new PipelineUnitTest();
+ unitTest.getTweaks().add(new
PipelineUnitTestTweak(PipelineTweak.REMOVE_TRANSFORM, "A"));
+
+ TestingGuiPlugin.applyTweakToTransform(unitTest, "A",
PipelineTweak.BYPASS_TRANSFORM, true);
+
+ assertEquals(1, unitTest.getTweaks().size());
+ assertEquals(PipelineTweak.BYPASS_TRANSFORM,
unitTest.findTweak("A").getTweak());
+ }
+
+ @Test
+ void applyTweakDisableRemovesOnlyMatchingType() {
+ PipelineUnitTest unitTest = new PipelineUnitTest();
+ unitTest.getTweaks().add(new
PipelineUnitTestTweak(PipelineTweak.BYPASS_TRANSFORM, "A"));
+ unitTest.getTweaks().add(new
PipelineUnitTestTweak(PipelineTweak.REMOVE_TRANSFORM, "B"));
+
+ // Disable REMOVE on A (which is bypassed) — leave A alone
+ TestingGuiPlugin.applyTweakToTransform(unitTest, "A",
PipelineTweak.REMOVE_TRANSFORM, false);
+ // Disable BYPASS on A — remove it
+ TestingGuiPlugin.applyTweakToTransform(unitTest, "A",
PipelineTweak.BYPASS_TRANSFORM, false);
+ // Disable REMOVE on B — remove it
+ TestingGuiPlugin.applyTweakToTransform(unitTest, "B",
PipelineTweak.REMOVE_TRANSFORM, false);
+
+ assertNull(unitTest.findTweak("A"));
+ assertNull(unitTest.findTweak("B"));
+ assertTrue(unitTest.getTweaks().isEmpty());
+ }
+
+ @Test
+ void applyTweakEnableOnMultipleTransforms() {
+ PipelineUnitTest unitTest = new PipelineUnitTest();
+
+ TestingGuiPlugin.applyTweakToTransform(unitTest, "A",
PipelineTweak.REMOVE_TRANSFORM, true);
+ TestingGuiPlugin.applyTweakToTransform(unitTest, "B",
PipelineTweak.REMOVE_TRANSFORM, true);
+ TestingGuiPlugin.applyTweakToTransform(unitTest, "C",
PipelineTweak.REMOVE_TRANSFORM, true);
+
+ assertEquals(3, unitTest.getTweaks().size());
+ assertEquals(PipelineTweak.REMOVE_TRANSFORM,
unitTest.findTweak("A").getTweak());
+ assertEquals(PipelineTweak.REMOVE_TRANSFORM,
unitTest.findTweak("B").getTweak());
+ assertEquals(PipelineTweak.REMOVE_TRANSFORM,
unitTest.findTweak("C").getTweak());
+ }
+
+ private static TransformMeta transform(String name, boolean selected) {
+ TransformMeta transformMeta = new TransformMeta();
+ transformMeta.setName(name);
+ transformMeta.setSelected(selected);
+ return transformMeta;
+ }
+}