Bug 61591

Summary: UX : Remove Workbench
Product: JMeter - Now in Github Reporter: Philippe Mouawad <p.mouawad>
Component: MainAssignee: JMeter issues mailing list <issues>
Status: RESOLVED FIXED    
Severity: enhancement CC: apc4, artem.fedorov, p.mouawad
Priority: P2    
Version: 3.3   
Target Milestone: ---   
Hardware: All   
OS: All   
Attachments: Remove WorkBench patch

Description Philippe Mouawad 2017-10-07 14:01:00 UTC
Workbench element should be removed in order to simplify UX.

The only advantage of this element is Non Test Elements which would be made available from Test Plan directly.

When running a test those element would not impact test plan.
Comment 1 Artem Fedorov 2017-11-14 13:51:40 UTC
Created attachment 35527 [details]
Remove WorkBench patch
Comment 2 Philippe Mouawad 2017-11-14 17:30:50 UTC
Hello Artem,
Thanks for your patch, would it be possible to provide a PR instead ?
It would allow us a better review and non regression tests are ran on the patch.

If you can't I'll do without it.

Regards
Comment 3 Andrey Pokhilko 2017-11-14 18:16:20 UTC
How can we avoid double effort? The "official" way to provide patch is to attach it to bugzilla. Now you require to create PR on GitHub, but GitHub PR is only for review, still disconnected from actual SVN repository. This process feels messy and discourages contributions...
Comment 4 Philippe Mouawad 2017-11-14 18:23:29 UTC
(In reply to Andrey Pokhilko from comment #3)
> How can we avoid double effort? The "official" way to provide patch is to
> attach it to bugzilla. Now you require to create PR on GitHub, but GitHub PR
> is only for review, still disconnected from actual SVN repository. This
> process feels messy and discourages contributions...

Hi Andrey,
Historically we favored patches. 
But we introduced PRs recently as long as Travis CI, they have a lot of advantages as you know (review, now code coverage impact check, automated tests...). 

That's why I asked here for it, BUT I said that I would take it as is if you don't want to provide a PR.

In summary, for next contributions, it would be nice to favor PR.
But for now, unless you want to make a PR, I'll take it as is.


PS : Do you really feel with all the efforts made on review, CI, ...  we discourage contributions ?
Comment 6 Andrey Pokhilko 2017-11-14 18:41:45 UTC
I re-checked the contributing page (http://jmeter.apache.org/building.html) and found that now the first option we mention is GitHub way. This means my intent to go with patches is outdated.

There is no problem with creating a PR, we'll do it soon. 

From my experience, the best thing is to require _only_ PR from contributors. PR on GitHub is perfect place for discussion, as it is contextual with the code. Also, discussion happens _before_ code merged, so it eliminates the post-commit investigations on dev mailing list.

Requirement to interact with Bugzilla reveals ugly nineties-style issue tracker, it serves bad reputation for us. IMO we should remove this requirement from contributors. If we need bugzillas, we (core maintainers) better create them ourselves. Working with SVN also don't manifest project as modern. 

But all of this were discussed so many times, and we had no decision to change this. I am ok with that, reasons make sense.
Comment 7 Artem Fedorov 2017-11-15 10:16:41 UTC
Added PR: https://github.com/apache/jmeter/pull/330

Attachment 35527 [details] is deprecated
Comment 8 Philippe Mouawad 2017-11-15 21:01:21 UTC
Author: pmouawad
Date: Wed Nov 15 21:00:51 2017
New Revision: 1815374

URL: http://svn.apache.org/viewvc?rev=1815374&view=rev
Log:
Bug 61591 - UX : Remove Workbench
Contributed by Artem Fedorov with modifications to fix the Popup Menu on the Non Test Elements that allows actions that are meaningless now
This closes #330
Bugzilla Id: 61591

Modified:
    jmeter/trunk/src/core/org/apache/jmeter/control/gui/TestPlanGui.java
    jmeter/trunk/src/core/org/apache/jmeter/control/gui/WorkBenchGui.java
    jmeter/trunk/src/core/org/apache/jmeter/gui/action/CheckDirty.java
    jmeter/trunk/src/core/org/apache/jmeter/gui/action/Load.java
    jmeter/trunk/src/core/org/apache/jmeter/gui/action/Move.java
    jmeter/trunk/src/core/org/apache/jmeter/gui/action/Save.java
    jmeter/trunk/src/core/org/apache/jmeter/gui/tree/JMeterTreeModel.java
    jmeter/trunk/src/core/org/apache/jmeter/gui/util/MenuFactory.java
    jmeter/trunk/src/core/org/apache/jmeter/testelement/WorkBench.java
    jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/control/gui/HttpMirrorControlGui.java
    jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/proxy/ProxyControl.java
    jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/proxy/gui/ProxyControlGui.java
    jmeter/trunk/xdocs/changes.xml
    jmeter/trunk/xdocs/usermanual/build-test-plan.xml
    jmeter/trunk/xdocs/usermanual/component_reference.xml
Comment 9 Antonio Gomes Rodrigues 2017-11-20 21:54:24 UTC
Date: Mon Nov 20 21:52:55 2017
New Revision: 1815862

URL: http://svn.apache.org/viewvc?rev=1815862&view=rev
Log:
[Bug 61591] Replace template_menu.png from get-started.html

Modified:
    jmeter/trunk/xdocs/images/screenshots/template_menu.png
Comment 10 Antonio Gomes Rodrigues 2017-11-20 22:37:02 UTC
New Revision: 1815865

URL: http://svn.apache.org/viewvc?rev=1815865&view=rev
Log:
[Bug 61591] Update build-web-test-plan documentation (image and text)

Modified:
    jmeter/trunk/xdocs/images/screenshots/webtest/http-defaults1.png
    jmeter/trunk/xdocs/images/screenshots/webtest/http-defaults2.png
    jmeter/trunk/xdocs/images/screenshots/webtest/http-request1.png
    jmeter/trunk/xdocs/images/screenshots/webtest/http-request2.png
    jmeter/trunk/xdocs/images/screenshots/webtest/http_login.png
    jmeter/trunk/xdocs/images/screenshots/webtest/threadgroup.png
    jmeter/trunk/xdocs/images/screenshots/webtest/threadgroup2.png
    jmeter/trunk/xdocs/usermanual/build-web-test-plan.xml
Comment 11 Milamber 2017-11-21 19:19:57 UTC
Some issues:

1/ If you add a HTTP(S) Test Script Recorder to the Test Plan, that's works. But if you make a cut (ctrl-x) and try to paste (ctrl-p) to the Test Plan : don't works

2/ Before when the workbench exists, you can do this: add a HTTP(S) Test Script Recorder to Workbench, and move the HTTP(S) Test Script Recorder into a Test Fragment element. (I follow this way to save my 'proxy elements (recorder, view result tree, recording controller, etc)' before the behavior to save workbench into the jmx file

I thinks that would be better to change the old jmx file with a save workbench to replace the workbench with a Test Fragment, and keep sub-elements inside.
Comment 12 Philippe Mouawad 2017-11-21 19:32:34 UTC
(In reply to Milamber from comment #11)
> Some issues:
> 
> 1/ If you add a HTTP(S) Test Script Recorder to the Test Plan, that's works.
> But if you make a cut (ctrl-x) and try to paste (ctrl-p) to the Test Plan :
> don't works
> 
> 2/ Before when the workbench exists, you can do this: add a HTTP(S) Test
> Script Recorder to Workbench, and move the HTTP(S) Test Script Recorder into
> a Test Fragment element. (I follow this way to save my 'proxy elements
> (recorder, view result tree, recording controller, etc)' before the behavior
> to save workbench into the jmx file
> 
> I thinks that would be better to change the old jmx file with a save
> workbench to replace the workbench with a Test Fragment, and keep
> sub-elements inside.

This is not clear for me, can you clarify what you want ?
Comment 13 Philippe Mouawad 2017-11-21 20:10:10 UTC
Author: pmouawad
Date: Tue Nov 21 20:00:29 2017
New Revision: 1815976

URL: http://svn.apache.org/viewvc?rev=1815976&view=rev
Log:
Bug 61591 - UX : Remove Workbench
Allow moving and copying Test Script Recorder under test plan
Allow moving and copying Test Script Recorder under Test Fragment
Bugzilla Id: 61591

Modified:
    jmeter/trunk/src/core/org/apache/jmeter/gui/util/MenuFactory.java
    
Author: pmouawad
Date: Tue Nov 21 20:08:52 2017
New Revision: 1815979

URL: http://svn.apache.org/viewvc?rev=1815979&view=rev
Log:
Bug 61591 - UX : Remove Workbench
Allow moving and copying Test Script Recorder under test plan
Allow moving and copying Test Script Recorder under Test Fragment
Bugzilla Id: 61591

Added:
    jmeter/trunk/src/core/org/apache/jmeter/testelement/NonTestElement.java   (with props)
Modified:
    jmeter/trunk/src/core/org/apache/jmeter/gui/util/MenuFactory.java
    jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/control/HttpMirrorServer.java
    jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/proxy/ProxyControl.java
Comment 14 Antonio Gomes Rodrigues 2017-11-21 21:55:07 UTC
New Revision: 1815991

URL: http://svn.apache.org/viewvc?rev=1815991&view=rev
Log:
[Bug 61591] Update jmeter_proxy_step_by_step (image and text)

Modified:
    jmeter/trunk/xdocs/images/screenshots/Proxy_Run.png
    jmeter/trunk/xdocs/images/screenshots/Select-Templates-Icon.png
    jmeter/trunk/xdocs/images/screenshots/Test_Generated.png
    jmeter/trunk/xdocs/images/screenshots/Validate-Test-Plan.png
    jmeter/trunk/xdocs/images/screenshots/example-recording.png
    jmeter/trunk/xdocs/images/screenshots/example-thread-group.png
    jmeter/trunk/xdocs/images/screenshots/http-config/http-request-defaults.png
    jmeter/trunk/xdocs/usermanual/jmeter_proxy_step_by_step.xml
Comment 15 Antonio Gomes Rodrigues 2017-11-21 21:56:38 UTC
New Revision: 1815993

URL: http://svn.apache.org/viewvc?rev=1815993&view=rev
Log:
[Bug 61591] Update templates : recording-with-think-time and recording

Modified:
    jmeter/trunk/bin/templates/recording-with-think-time.jmx
    jmeter/trunk/bin/templates/recording.jmx
Comment 16 Sapan 2018-03-22 20:16:03 UTC
Comment on attachment 35527 [details]
Remove WorkBench patch

>Index: xdocs/changes.xml
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- xdocs/changes.xml	(date 1510611537000)
>+++ xdocs/changes.xml	(date 1510663205000)
>@@ -155,6 +155,7 @@
>     <li><bug>61697</bug>Introduce Darcula Look And Feel to make JMeter UI more attractive</li>
>     <li><bug>61704</bug>Toolbar : Improve a bit the right part</li>
>     <li><bug>61731</bug>Enhance Test plan Backup with option to save before run. Based on a contribution by orimarko at gmail.com</li>
>+    <li>Drop Workbench from test tree. Implemented by Artem Fedorov (artem at blazemeter.com) and contributed by BlazeMeter Ltd.</li>
> </ul>
> 
> <ch_section>Non-functional changes</ch_section>
>Index: docs/usermanual/build-test-plan.html
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>ISO-8859-15
>===================================================================
>--- docs/usermanual/build-test-plan.html	(date 1510611537000)
>+++ docs/usermanual/build-test-plan.html	(date 1510663205000)
>@@ -229,10 +229,6 @@
> you can save test tree fragments and individual elements for later use.</p>
> 
> 
>-<div class="clear"></div>
>-<div class="note">By default, the workbench is not automatically saved with the test plan, but it can be saved by checking "<span class="code">Save Workbench</span>" option on Workbench element.</div>
>-<div class="clear"></div>
>-
> </div>
> 
> 
>Index: xdocs/usermanual/build-test-plan.xml
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- xdocs/usermanual/build-test-plan.xml	(date 1510611537000)
>+++ xdocs/usermanual/build-test-plan.xml	(date 1510663205000)
>@@ -53,7 +53,6 @@
> JMeter will save the element selected, plus all child elements beneath it.  In this way,
> you can save test tree fragments and individual elements for later use.</p>
> 
>-<note>By default, the workbench is not automatically saved with the test plan, but it can be saved by checking "<code>Save Workbench</code>" option on Workbench element.</note>
> </subsection>
> 
> <subsection name="&sect-num;.3 Configuring Tree Elements" anchor="config_element">
>Index: docs/usermanual/component_reference.html
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>ISO-8859-15
>===================================================================
>--- docs/usermanual/component_reference.html	(date 1510611537000)
>+++ docs/usermanual/component_reference.html	(date 1510663205000)
>@@ -591,9 +591,6 @@
> <a href="#Thread_Group">Thread Group</a>
> </li>
> <li>
>-<a href="#WorkBench">WorkBench</a>
>-</li>
>-<li>
> <a href="#SSL_Manager">SSL Manager</a>
> </li>
> <li>
>@@ -6556,9 +6553,6 @@
> <figcaption>Screenshot of Control-Panel of Module Controller</figcaption>
> </figure>
> </div>
>-<div class="clear"></div>
>-<div class="note">The Module Controller should not be used with remote testing or non-gui testing in conjunction with Workbench components since the Workbench test elements are not part of test plan <span class="code">.jmx</span> files.  Any such test will fail.</div>
>-<div class="clear"></div>
> <div class="properties">
> <h3 id="Module_Controller_parms1">
>         Parameters
>@@ -16026,66 +16020,6 @@
> <div class="required req-false">No</div>
> </div>
> 
>-</div>
>-<div class="go-top">
>-<a href="#">^</a>
>-</div>
>-</div>
>-
>-
>-<div class="component">
>-<h2 id="WorkBench">WorkBench<a class="sectionlink" href="#WorkBench" title="Link to here">&para;</a>
>-</h2>
>-<div class="description">
>-
>-<p>The WorkBench simply provides a place to temporarily store test elements while not in use, for copy/paste purposes, or any other purpose you desire. 
>-When you save your test plan, WorkBench items are not saved with it by default unless you check "<span class="code">Save Workbench</span>" option.
>-Your WorkBench can be saved independently, if you like (right-click on <span class="code">WorkBench</span> and choose <span class="code">Save</span>).</p>
>-
>-<p>Certain test elements are only available on the WorkBench:</p>
>-
>-<ul>
>-
>-<li>
>-<a href="../usermanual/component_reference.html#HTTP(S)_Test_Script_Recorder">HTTP(S) Test Script Recorder</a>
>-</li>
>-
>-<li>
>-<a href="../usermanual/component_reference.html#HTTP_Mirror_Server">HTTP Mirror Server</a>
>-</li>
>-
>-<li>
>-<a href="../usermanual/component_reference.html#Property_Display">Property Display</a>
>-</li>
>-
>-</ul>
>-
>-<div class="properties">
>-<h3>
>-        Parameters
>-        </h3>
>-<div class="property title">
>-<div class="name title">Attribute</div>
>-<div class="description title">Description</div>
>-<div class="required title">Required</div>
>-</div>
>-         
>-<div class="property">
>-<div class="name req-false">Save WorkBench</div>
>-<div class="description req-false">
>-                Allow to save the WorkBench's elements into the JMX file.
>-        </div>
>-<div class="required req-false">No</div>
>-</div>
>-
>-</div>
>-
>-</div>
>-<div class="screenshot">
>-<figure>
>-<a href="../images/screenshots/workbench.png"><img src="../images/screenshots/workbench.png" width="384" height="103" alt="Screenshot for Control-Panel of WorkBench"></a>
>-<figcaption>Screenshot of Control-Panel of WorkBench</figcaption>
>-</figure>
> </div>
> <div class="go-top">
> <a href="#">^</a>
>Index: xdocs/usermanual/component_reference.xml
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- xdocs/usermanual/component_reference.xml	(date 1510611537000)
>+++ xdocs/usermanual/component_reference.xml	(date 1510663205000)
>@@ -2482,7 +2482,6 @@
> otherwise a duplicate may be accidentally created when new elements are added to the test plan. 
> </p>
> </description>
>-<note>The Module Controller should not be used with remote testing or non-gui testing in conjunction with Workbench components since the Workbench test elements are not part of test plan <code>.jmx</code> files.  Any such test will fail.</note>
> <properties>
>         <property name="Name" required="No">Descriptive name for this controller that is shown in the tree.</property>
>         <property name="Module to Run" required="Yes">The module controller provides a list of all controllers loaded into the gui.  Select
>@@ -6374,24 +6373,6 @@
> </properties>
> </component>
> 
>-<component name="WorkBench" index="&sect-num;.9.3"  width="384" height="103" screenshot="workbench.png">
>-<description>
>-<p>The WorkBench simply provides a place to temporarily store test elements while not in use, for copy/paste purposes, or any other purpose you desire. 
>-When you save your test plan, WorkBench items are not saved with it by default unless you check "<code>Save Workbench</code>" option.
>-Your WorkBench can be saved independently, if you like (right-click on <code>WorkBench</code> and choose <code>Save</code>).</p>
>-<p>Certain test elements are only available on the WorkBench:</p>
>-<ul>
>-<li><complink name="HTTP(S) Test Script Recorder"/></li>
>-<li><complink name="HTTP Mirror Server"/></li>
>-<li><complink name="Property Display"/></li>
>-</ul>
>-<properties>
>-         <property name="Save WorkBench" required="No">
>-                Allow to save the WorkBench's elements into the JMX file.
>-        </property>
>-</properties>
>-</description>
>-</component>
> 
> <component name="SSL Manager" index="&sect-num;.9.4" screenshot="">
> <p>
>Index: src/core/org/apache/jmeter/gui/action/Load.java
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- src/core/org/apache/jmeter/gui/action/Load.java	(date 1510611537000)
>+++ src/core/org/apache/jmeter/gui/action/Load.java	(date 1510663205000)
>@@ -38,7 +38,6 @@
> import org.apache.jmeter.services.FileServer;
> import org.apache.jmeter.testelement.TestElement;
> import org.apache.jmeter.testelement.TestPlan;
>-import org.apache.jmeter.testelement.WorkBench;
> import org.apache.jmeter.util.JMeterUtils;
> import org.apache.jorphan.collections.HashTree;
> import org.slf4j.Logger;
>@@ -181,7 +180,7 @@
> 
>         if (merging){ // Check if target of merge is reasonable
>             final TestElement te = (TestElement)tree.getArray()[0];
>-            if (!(te instanceof WorkBench || te instanceof TestPlan)){// These are handled specially by addToTree
>+            if (!(te instanceof TestPlan)){// These are handled specially by addToTree
>                 final boolean ok = MenuFactory.canAddTo(guiInstance.getCurrentNode(), te);
>                 if (!ok){
>                     String name = te.getName();
>Index: src/core/org/apache/jmeter/gui/action/Move.java
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- src/core/org/apache/jmeter/gui/action/Move.java	(date 1510611537000)
>+++ src/core/org/apache/jmeter/gui/action/Move.java	(date 1510663205000)
>@@ -33,7 +33,6 @@
> import org.apache.jmeter.gui.util.MenuFactory;
> import org.apache.jmeter.testelement.TestElement;
> import org.apache.jmeter.testelement.TestPlan;
>-import org.apache.jmeter.testelement.WorkBench;
> 
> /**
>  * Move a node up/down/left/right 
>@@ -120,7 +119,7 @@
>     private JMeterTreeNode getParentNode(JMeterTreeNode currentNode) {
>         JMeterTreeNode parentNode = (JMeterTreeNode) currentNode.getParent();
>         TestElement te = currentNode.getTestElement();
>-        if (te instanceof TestPlan || te instanceof WorkBench) {
>+        if (te instanceof TestPlan) {
>             parentNode = null; // So elements can only be added as children
>         }
>         return parentNode;
>Index: src/core/org/apache/jmeter/gui/action/Save.java
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- src/core/org/apache/jmeter/gui/action/Save.java	(date 1510611537000)
>+++ src/core/org/apache/jmeter/gui/action/Save.java	(date 1510663205000)
>@@ -50,7 +50,6 @@
> import org.apache.jmeter.services.FileServer;
> import org.apache.jmeter.testelement.TestElement;
> import org.apache.jmeter.testelement.TestPlan;
>-import org.apache.jmeter.testelement.WorkBench;
> import org.apache.jmeter.threads.ThreadGroup;
> import org.apache.jmeter.util.JMeterUtils;
> import org.apache.jorphan.collections.HashTree;
>@@ -163,13 +162,7 @@
>             }
>         } else {
>             fullSave = true;
>-            HashTree testPlan = GuiPackage.getInstance().getTreeModel().getTestPlan();
>-            // If saveWorkBench 
>-            if (isWorkbenchSaveable()) {
>-                HashTree workbench = GuiPackage.getInstance().getTreeModel().getWorkBench();
>-                testPlan.add(workbench);
>-            }
>-            subTree = testPlan;
>+            subTree = GuiPackage.getInstance().getTreeModel().getTestPlan();
>         }
> 
>         String updateFile = GuiPackage.getInstance().getTestPlanFile();
>@@ -225,10 +218,6 @@
>             if (fullSave) { // Only update the stored copy of the tree for a full save
>                 FileServer.getFileServer().setScriptName(new File(updateFile).getName());
>                 subTree = GuiPackage.getInstance().getTreeModel().getTestPlan(); // refetch, because convertSubTree affects it
>-                if (isWorkbenchSaveable()) {
>-                    HashTree workbench = GuiPackage.getInstance().getTreeModel().getWorkBench();
>-                    subTree.add(workbench);
>-                }
>                 ActionRouter.getInstance().doActionNow(new ActionEvent(subTree, e.getID(), ActionNames.SUB_TREE_SAVED));
>             }
>             
>@@ -396,13 +385,6 @@
>                 .orElse(0);
>     }
>     
>-    /**
>-     * check if the workbench should be saved
>-     */
>-    private boolean isWorkbenchSaveable() {
>-        JMeterTreeNode workbenchNode = (JMeterTreeNode) ((JMeterTreeNode) GuiPackage.getInstance().getTreeModel().getRoot()).getChildAt(1);
>-        return ((WorkBench) workbenchNode.getUserObject()).getSaveWorkBench();
>-    }
> 
>     /**
>      * Check nodes does not contain a node of type TestPlan or ThreadGroup
>Index: src/core/org/apache/jmeter/gui/util/MenuFactory.java
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- src/core/org/apache/jmeter/gui/util/MenuFactory.java	(date 1510611537000)
>+++ src/core/org/apache/jmeter/gui/util/MenuFactory.java	(date 1510663205000)
>@@ -53,7 +53,6 @@
> import org.apache.jmeter.testbeans.gui.TestBeanGUI;
> import org.apache.jmeter.testelement.TestElement;
> import org.apache.jmeter.testelement.TestPlan;
>-import org.apache.jmeter.testelement.WorkBench;
> import org.apache.jmeter.util.JMeterUtils;
> import org.apache.jmeter.visualizers.Printable;
> import org.apache.jorphan.gui.GuiUtils;
>@@ -616,9 +615,6 @@
>         if (null == parentNode) {
>             return false;
>         }
>-        if (foundClass(nodes, new Class[]{WorkBench.class})){// Can't add a Workbench anywhere
>-            return false;
>-        }
>         if (foundClass(nodes, new Class[]{TestPlan.class})){// Can't add a TestPlan anywhere
>             return false;
>         }
>@@ -632,9 +628,11 @@
>             return false;
>         }
> 
>-        if (parent instanceof WorkBench) {// allow everything else
>-            return true;
>+        // Cannot move Non-Test Elements from root of Test Plan
>+        if (!(parent instanceof TestPlan) && foundMenuCategories(nodes, NON_TEST_ELEMENTS)) {
>+            return false;
>         }
>+
>         if (parent instanceof TestPlan) {
>             if (foundClass(nodes,
>                      new Class[]{Sampler.class, Controller.class}, // Samplers and Controllers need not apply ...
>@@ -657,6 +655,7 @@
>             }
>             return true;
>         }
>+
>         // All other
>         return false;
>     }
>@@ -672,6 +671,18 @@
>         }
>         return false;
>     }
>+
>+    // Is any node an instance of one of the menu category?
>+    private static boolean foundMenuCategories(JMeterTreeNode[] nodes, String category) {
>+        for (JMeterTreeNode node : nodes) {
>+            for (String c : node.getMenuCategories()) {
>+                if (category.equals(c)) {
>+                    return true;
>+                }
>+            }
>+        }
>+        return false;
>+    }
> 
>     // Is any node an instance of one of the classes, but not an exception?
>     private static boolean foundClass(JMeterTreeNode[] nodes, Class<?>[] classes, Class<?> except) {
>Index: src/core/org/apache/jmeter/gui/action/CheckDirty.java
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- src/core/org/apache/jmeter/gui/action/CheckDirty.java	(date 1510611537000)
>+++ src/core/org/apache/jmeter/gui/action/CheckDirty.java	(date 1510663205000)
>@@ -28,7 +28,6 @@
> import org.apache.jmeter.gui.GuiPackage;
> import org.apache.jmeter.gui.tree.JMeterTreeNode;
> import org.apache.jmeter.testelement.TestElement;
>-import org.apache.jmeter.testelement.WorkBench;
> import org.apache.jorphan.collections.HashTree;
> import org.apache.jorphan.collections.HashTreeTraverser;
> import org.apache.jorphan.collections.ListedHashTree;
>@@ -91,9 +90,6 @@
>         } else if (action.equals(ActionNames.ADD_ALL)) {
>             previousGuiItems.clear();
>             GuiPackage.getInstance().getTreeModel().getTestPlan().traverse(this);
>-            if (isWorkbenchSaveable()) {
>-                GuiPackage.getInstance().getTreeModel().getWorkBench().traverse(this);
>-            }
>         } else if (action.equals(ActionNames.CHECK_REMOVE) ||
>                 action.equals(ActionNames.CHECK_CUT)) {
>             GuiPackage guiPackage = GuiPackage.getInstance();
>@@ -118,9 +114,6 @@
>             //remember
>             previousGuiItems.clear();
>             GuiPackage.getInstance().getTreeModel().getTestPlan().traverse(this);
>-            if (isWorkbenchSaveable()) {
>-                GuiPackage.getInstance().getTreeModel().getWorkBench().traverse(this);
>-            }
>         }
>         else {
>             dirty = false;
>@@ -129,13 +122,6 @@
>                 HashTree wholeTree = GuiPackage.getInstance().getTreeModel().getTestPlan();
>                 wholeTree.traverse(this);
>                 
>-                // check the workbench for modification
>-                if(!dirty) { // NOSONAR
>-                    if (isWorkbenchSaveable()) {
>-                        HashTree workbench = GuiPackage.getInstance().getTreeModel().getWorkBench();
>-                        workbench.traverse(this);
>-                    }
>-                }
>             } finally {
>                 checkMode = false;
>             }
>@@ -143,13 +129,6 @@
>         GuiPackage.getInstance().setDirty(dirty);
>     }
> 
>-    /**
>-     * check if the workbench should be saved
>-     */
>-    private boolean isWorkbenchSaveable() {
>-        JMeterTreeNode workbenchNode = (JMeterTreeNode) ((JMeterTreeNode) GuiPackage.getInstance().getTreeModel().getRoot()).getChildAt(1);
>-        return ((WorkBench) workbenchNode.getUserObject()).getSaveWorkBench();
>-    }
> 
>     /**
>      * The tree traverses itself depth-first, calling addNode for each
>Index: src/core/org/apache/jmeter/control/gui/TestPlanGui.java
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- src/core/org/apache/jmeter/control/gui/TestPlanGui.java	(date 1510611537000)
>+++ src/core/org/apache/jmeter/control/gui/TestPlanGui.java	(date 1510663205000)
>@@ -92,6 +92,7 @@
>         JMenu addMenu = new JMenu(JMeterUtils.getResString("add")); // $NON-NLS-1$
>         addMenu.add(MenuFactory.makeMenu(MenuFactory.THREADS, ActionNames.ADD));
>         addMenu.add(MenuFactory.makeMenu(MenuFactory.FRAGMENTS, ActionNames.ADD));
>+        addMenu.add(MenuFactory.makeMenu(MenuFactory.NON_TEST_ELEMENTS, ActionNames.ADD));
>         addMenu.add(MenuFactory.makeMenu(MenuFactory.CONFIG_ELEMENTS, ActionNames.ADD));
>         addMenu.add(MenuFactory.makeMenu(MenuFactory.TIMERS, ActionNames.ADD));
>         addMenu.add(MenuFactory.makeMenu(MenuFactory.PRE_PROCESSORS, ActionNames.ADD));
>Index: src/core/org/apache/jmeter/control/gui/WorkBenchGui.java
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- src/core/org/apache/jmeter/control/gui/WorkBenchGui.java	(date 1510611537000)
>+++ src/core/org/apache/jmeter/control/gui/WorkBenchGui.java	(date 1510663205000)
>@@ -38,6 +38,7 @@
>  * preparations for the test plan.
>  *
>  */
>+@Deprecated
> public class WorkBenchGui extends AbstractJMeterGuiComponent {
>     private static final long serialVersionUID = 240L;
>     // This check-box defines whether to save  WorkBench content or not
>Index: src/core/org/apache/jmeter/gui/tree/JMeterTreeModel.java
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- src/core/org/apache/jmeter/gui/tree/JMeterTreeModel.java	(date 1510611537000)
>+++ src/core/org/apache/jmeter/gui/tree/JMeterTreeModel.java	(date 1510663205000)
>@@ -18,6 +18,7 @@
> 
> package org.apache.jmeter.gui.tree;
> 
>+import java.util.Collection;
> import java.util.Enumeration;
> import java.util.LinkedList;
> import java.util.List;
>@@ -25,11 +26,13 @@
> import javax.swing.tree.DefaultTreeModel;
> 
> import org.apache.jmeter.config.gui.AbstractConfigGui;
>+import org.apache.jmeter.control.TestFragmentController;
>+import org.apache.jmeter.control.gui.TestFragmentControllerGui;
> import org.apache.jmeter.control.gui.TestPlanGui;
>-import org.apache.jmeter.control.gui.WorkBenchGui;
> import org.apache.jmeter.exceptions.IllegalUserActionException;
> import org.apache.jmeter.gui.GuiPackage;
> import org.apache.jmeter.gui.JMeterGUIComponent;
>+import org.apache.jmeter.gui.util.MenuFactory;
> import org.apache.jmeter.testelement.TestElement;
> import org.apache.jmeter.testelement.TestPlan;
> import org.apache.jmeter.testelement.WorkBench;
>@@ -40,13 +43,13 @@
> 
>     private static final long serialVersionUID = 240L;
> 
>-    public JMeterTreeModel(TestElement tp, TestElement wb) {
>-        super(new JMeterTreeNode(wb, null));
>-        initTree(tp,wb);
>+    public JMeterTreeModel(TestElement tp) {
>+        super(new JMeterTreeNode(tp, null));
>+        initTree(tp);
>     }
> 
>     public JMeterTreeModel() {
>-        this(new TestPlanGui().createTestElement(),new WorkBenchGui().createTestElement());
>+        this(new TestPlanGui().createTestElement());
>     }
> 
>     /**
>@@ -57,7 +60,7 @@
>      */
>     @Deprecated
>     public JMeterTreeModel(Object o) {
>-        this(new TestPlan(),new WorkBench());
>+        this(new TestPlan());
>     }
> 
>     /**
>@@ -90,13 +93,11 @@
>      *            <code>current</code>
>      * @param current
>      *            The node in which the <code>subTree</code> is to be inserted.
>-     *            Will be overridden, when an instance of {@link TestPlan} or
>-     *            {@link WorkBench} is found in the subtree.
>+     *            Will be overridden, when an instance of {@link TestPlan}
>      * @return newly created sub tree now found at <code>current</code>
>      * @throws IllegalUserActionException
>      *             when <code>current</code> is not an instance of
>      *             {@link AbstractConfigGui} and no instance of {@link TestPlan}
>-     *             or {@link WorkBench} could be found in the
>      *             <code>subTree</code>
>      */
>     public HashTree addSubTree(HashTree subTree, JMeterTreeNode current) throws IllegalUserActionException {
>@@ -112,11 +113,11 @@
>                 userObject.setSerialized(tp.isSerialized());
>                 addSubTree(subTree.getTree(item), current);
>             } else if (item instanceof WorkBench) {
>-                current = (JMeterTreeNode) ((JMeterTreeNode) getRoot()).getChildAt(1);
>-                final TestElement testElement = (TestElement) current.getUserObject();
>-                testElement.addTestElement(item);
>-                testElement.setName(item.getName());
>-                addSubTree(subTree.getTree(item), current);
>+                //Move item from WorkBench to TestPlan
>+                HashTree workbenchTree = subTree.getTree(item);
>+                if (workbenchTree.size() > 0) {
>+                    moveWorkBenchToTestPlan(current, workbenchTree);
>+                }
>             } else {
>                 addSubTree(subTree.getTree(item), addComponent(item, current));
>             }
>@@ -164,7 +165,7 @@
>     }
> 
>     public void removeNodeFromParent(JMeterTreeNode node) {
>-        if (!(node.getUserObject() instanceof TestPlan) && !(node.getUserObject() instanceof WorkBench)) {
>+        if (!(node.getUserObject() instanceof TestPlan)) {
>             super.removeNodeFromParent(node);
>         }
>     }
>@@ -218,13 +219,6 @@
>         return getCurrentSubTree((JMeterTreeNode) ((JMeterTreeNode) this.getRoot()).getChildAt(0));
>     }
> 
>-    /**
>-     * Get the {@link WorkBench} from the root of this tree
>-     * @return The {@link WorkBench} found at the root of this tree
>-     */
>-    public HashTree getWorkBench() {
>-        return getCurrentSubTree((JMeterTreeNode) ((JMeterTreeNode) this.getRoot()).getChildAt(1));
>-    }
> 
>     /**
>      * Clear the test plan, and use default node for test plan and workbench.
>@@ -252,23 +246,66 @@
>             children = getChildCount(getRoot());
>         }
>         // Init the tree
>-        initTree(testPlan,new WorkBenchGui().createTestElement()); // Assumes this is only called from GUI mode
>+        initTree(testPlan); // Assumes this is only called from GUI mode
>     }
> 
>     /**
>      * Initialize the model with nodes for testplan and workbench.
>      *
>      * @param tp the element to use as testplan
>-     * @param wb the element to use as workbench
>      */
>-    private void initTree(TestElement tp, TestElement wb) {
>+    private void initTree(TestElement tp) {
>         // Insert the test plan node
>         insertNodeInto(new JMeterTreeNode(tp, this), (JMeterTreeNode) getRoot(), 0);
>-        // Insert the workbench node
>-        insertNodeInto(new JMeterTreeNode(wb, this), (JMeterTreeNode) getRoot(), 1);
>         // Let others know that the tree content has changed.
>         // This should not be necessary, but without it, nodes are not shown when the user
>         // uses the Close menu item
>         nodeStructureChanged((JMeterTreeNode)getRoot());
>     }
>+
>+
>+    /**
>+     * Move all Non-Test Elements from WorkBench to TestPlan root.
>+     * Other Test Elements will be move to WorkBench Test Fragment in TestPlan
>+     * @param current - TestPlan root
>+     * @param workbenchTree - WorkBench hash tree
>+     */
>+    private void moveWorkBenchToTestPlan(JMeterTreeNode current, HashTree workbenchTree) throws IllegalUserActionException {
>+        Object[] workbenchTreeArray = workbenchTree.getArray();
>+        for (Object node : workbenchTreeArray) {
>+            if (isNonTestElement(node)) {
>+                HashTree subtree = workbenchTree.getTree(node);
>+                workbenchTree.remove(node);
>+                HashTree tree = new HashTree();
>+                tree.add(node);
>+                tree.add(node, subtree);
>+                ((TestElement) node).setProperty(TestElement.ENABLED, false);
>+                addSubTree(tree, current);
>+            }
>+        }
>+
>+        if (workbenchTree.size() > 0) {
>+            HashTree testFragmentTree = new HashTree();
>+            TestFragmentController testFragmentController = new TestFragmentController();
>+            testFragmentController.setProperty(TestElement.NAME, "WorkBench Test Fragment");
>+            testFragmentController.setProperty(TestElement.GUI_CLASS, TestFragmentControllerGui.class.getName());
>+            testFragmentController.setProperty(TestElement.ENABLED, false);
>+            testFragmentTree.add(testFragmentController);
>+            testFragmentTree.add(testFragmentController, workbenchTree);
>+            addSubTree(testFragmentTree, current);
>+        }
>+    }
>+
>+    private boolean isNonTestElement(Object node) {
>+        JMeterTreeNode treeNode = new JMeterTreeNode((TestElement) node, null);
>+        Collection<String> categories = treeNode.getMenuCategories();
>+        if (categories != null) {
>+            for (String category : categories) {
>+                if (MenuFactory.NON_TEST_ELEMENTS.equals(category)) {
>+                    return true;
>+                }
>+            }
>+        }
>+        return false;
>+    }
> }
>Index: src/protocol/http/org/apache/jmeter/protocol/http/proxy/ProxyControl.java
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- src/protocol/http/org/apache/jmeter/protocol/http/proxy/ProxyControl.java	(date 1510611537000)
>+++ src/protocol/http/org/apache/jmeter/protocol/http/proxy/ProxyControl.java	(date 1510663205000)
>@@ -83,7 +83,6 @@
> import org.apache.jmeter.testelement.TestElement;
> import org.apache.jmeter.testelement.TestPlan;
> import org.apache.jmeter.testelement.TestStateListener;
>-import org.apache.jmeter.testelement.WorkBench;
> import org.apache.jmeter.testelement.property.BooleanProperty;
> import org.apache.jmeter.testelement.property.CollectionProperty;
> import org.apache.jmeter.testelement.property.IntegerProperty;
>@@ -1055,7 +1054,6 @@
>      * <li>The controller specified by the <code>target</code> property.
>      * <li>If none was specified, the first RecordingController in the tree.
>      * <li>If none is found, the first AbstractThreadGroup in the tree.
>-     * <li>If none is found, the Workspace.
>      * </ul>
>      *
>      * @return the tree node for the controller where the proxy must store the
>@@ -1073,10 +1071,6 @@
>         myTarget = findFirstNodeOfType(AbstractThreadGroup.class);
>         if (myTarget != null) {
>             return myTarget;
>-        }
>-        myTarget = findFirstNodeOfType(WorkBench.class);
>-        if (myTarget != null) {
>-            return myTarget;
>         }
>         log.error("Program error: test script recording target not found.");
>         return null;
>Index: src/protocol/http/org/apache/jmeter/protocol/http/proxy/gui/ProxyControlGui.java
>IDEA additional info:
>Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
><+>UTF-8
>===================================================================
>--- src/protocol/http/org/apache/jmeter/protocol/http/proxy/gui/ProxyControlGui.java	(date 1510611537000)
>+++ src/protocol/http/org/apache/jmeter/protocol/http/proxy/gui/ProxyControlGui.java	(date 1510663205000)
>@@ -77,7 +77,6 @@
> import org.apache.jmeter.protocol.http.sampler.HTTPSamplerFactory;
> import org.apache.jmeter.testelement.TestElement;
> import org.apache.jmeter.testelement.TestPlan;
>-import org.apache.jmeter.testelement.WorkBench;
> import org.apache.jmeter.testelement.property.PropertyIterator;
> import org.apache.jmeter.util.JMeterUtils;
> import org.apache.jorphan.exec.KeyToolUtils;
>@@ -1131,7 +1130,7 @@
>                     targetNodesModel.addElement(tnw);
>                     name.append(separator);
>                     buildNodesModel(cur, name.toString(), level + 1);
>-                } else if (te instanceof TestPlan || te instanceof WorkBench) {
>+                } else if (te instanceof TestPlan) {
>                     name.append(cur.getName());
>                     name.append(separator);
>                     buildNodesModel(cur, name.toString(), 0);
Comment 17 The ASF infrastructure team 2022-09-24 20:38:10 UTC
This issue has been migrated to GitHub: https://github.com/apache/jmeter/issues/4511