Desktop: prevent incorrect filtering of 'formActive' event

Problem:
When the UI server hides the current form and instead shows another
form, the handling of the "hide form" event causes a 'formActive=null'
event to be sent to the server (queued). When later the "show form"
event is processed, an event filter prevents that a second 'formActive'
event (with the new form as value) is sent to the server. As a
consequence, the UI server will no longer have the same state as the
browser.

Solution:
Before adding the event filter, DesktopAdapter needs to check if the
current request queue contains a 'formActivate' event. If yes, the event
filter must not be added.

253018

Change-Id: I9c1f1d663f6d9cfb7804b7f1e4390f2cc6f79f00
Reviewed-on: https://git.eclipse.org/r/147847
Tested-by: CI Bot
Reviewed-by: Claudio Guglielmo <claudio.guglielmo@bsiag.com>
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/DesktopAdapterSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/DesktopAdapterSpec.js
index e3c3117..b83e033 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/DesktopAdapterSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/DesktopAdapterSpec.js
@@ -72,6 +72,89 @@
       });
       expect(mostRecentJsonRequest()).toContainEvents(event);
     });
+
+    it('can close and open new form in the same response', function() {
+      var formModel = createAndRegisterFormModel();
+      var form = session.getOrCreateWidget(formModel.id, desktop);
+      desktop.dialogs = [form];
+      session._renderDesktop();
+
+      desktop.activateForm(form);
+      expect(desktop.activeForm).toBe(form);
+
+      expect(jasmine.Ajax.requests.count()).toBe(0);
+
+      sendQueuedAjaxCalls();
+      expect(jasmine.Ajax.requests.count()).toBe(1);
+
+      // ------------------------
+
+      // Close form and open new form --> new form must be activated
+
+      var response = {
+        adapterData: {
+          '400': {
+            displayHint: 'view',
+            global: true,
+            id: '400',
+            objectType: 'Form',
+            owner: '1',
+            rootGroupBox: '401'
+          },
+          '401': {
+            fields: [],
+            id: '401',
+            objectType: 'GroupBox',
+            owner: '400'
+          }
+        },
+        events: [
+          {
+            target: desktopAdapter.id,
+            type: 'formHide',
+            displayParent:  desktopAdapter.id,
+            form: formModel.id
+          },
+          {
+            target: desktopAdapter.id,
+            type: 'formShow',
+            displayParent:  desktopAdapter.id,
+            form: '400'
+          }
+        ]
+      };
+      session._processSuccessResponse(response);
+      sendQueuedAjaxCalls();
+
+      var expectedEvents = [
+        new scout.RemoteEvent(desktopAdapter.id, 'formActivate', {
+          formId: null
+        }),
+        new scout.RemoteEvent(desktopAdapter.id, 'formActivate', {
+          formId: '400'
+        })
+      ];
+      expect(mostRecentJsonRequest()).toContainEventsExactly(expectedEvents);
+      expect(jasmine.Ajax.requests.count()).toBe(2);
+
+      // ------------------------
+
+      // Only hide form --> no formActivate event is sent
+
+      response = {
+        events: [
+          {
+            target: desktopAdapter.id,
+            type: 'formHide',
+            displayParent:  desktopAdapter.id,
+            form: '400'
+          }
+        ]
+      };
+      session._processSuccessResponse(response);
+      sendQueuedAjaxCalls();
+      expect(jasmine.Ajax.requests.count()).toBe(2);
+    });
   });
 
   describe('onFormShow', function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopAdapter.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopAdapter.js
index 9632a36..d643452 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopAdapter.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopAdapter.js
@@ -66,11 +66,17 @@
 
   if (displayParent) {
     form = this.session.getOrCreateWidget(event.form, displayParent.widget);
-    this.addFilterForWidgetEvent(function(widgetEvent) {
-      return (widgetEvent.type === 'formActivate' &&
-        widgetEvent.form === form);
-    });
     form.setDisplayParent(displayParent.widget);
+
+    var hasPendingFormActivateEvent = this.session.asyncEvents.some(function(event) {
+      return event.type === 'formActivate' && event.target === this.id;
+    }, this);
+    if (!hasPendingFormActivateEvent) {
+      this.addFilterForWidgetEvent(function(widgetEvent) {
+        return (widgetEvent.type === 'formActivate' && widgetEvent.form === form);
+      }.bind(this));
+    }
+
     this.widget.showForm(form, event.position);
   }
 };