This is an automated email from the ASF dual-hosted git repository.

tenthe pushed a commit to branch fix-e2e-tests
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit a88abe7f807eb52d11aa85947d6e85fb37219a79
Author: Philipp Zehnder <[email protected]>
AuthorDate: Mon Jul 27 11:30:43 2026 +0000

    fix: persist adapter asset links on update
---
 ui/cypress/support/utils/connect/ConnectBtns.ts    |  16 +++
 ui/cypress/support/utils/connect/ConnectUtils.ts   |  16 +++
 ui/cypress/tests/connect/adapterWithAssets.spec.ts |  10 +-
 .../adapter-configuration.component.ts             |  19 +++-
 .../adapter-started-dialog.component.ts            | 123 +++++++++++++--------
 5 files changed, 128 insertions(+), 56 deletions(-)

diff --git a/ui/cypress/support/utils/connect/ConnectBtns.ts 
b/ui/cypress/support/utils/connect/ConnectBtns.ts
index 6d300ea502..1d2dcf1d58 100644
--- a/ui/cypress/support/utils/connect/ConnectBtns.ts
+++ b/ui/cypress/support/utils/connect/ConnectBtns.ts
@@ -56,6 +56,22 @@ export class ConnectBtns {
         GeneralUtils.openMenuForRow(adapterName);
     }
 
+    public static adapterConfigurationOptions() {
+        return cy.dataCy('options-adapter', { timeout: 10000 });
+    }
+
+    public static manageAdapter() {
+        return cy.dataCy('manage-adapter-btn', { timeout: 10000 });
+    }
+
+    public static managedResourceName() {
+        return cy.dataCy('managed-resource-name', { timeout: 10000 });
+    }
+
+    public static manageResourceSave() {
+        return cy.dataCy('sp-manage-save', { timeout: 10000 });
+    }
+
     public static refreshSchema() {
         return cy.dataCy('refresh-schema');
     }
diff --git a/ui/cypress/support/utils/connect/ConnectUtils.ts 
b/ui/cypress/support/utils/connect/ConnectUtils.ts
index 38fb88c406..1ead7ab2e5 100644
--- a/ui/cypress/support/utils/connect/ConnectUtils.ts
+++ b/ui/cypress/support/utils/connect/ConnectUtils.ts
@@ -148,6 +148,22 @@ export class ConnectUtils {
         ConnectBtns.adapterNameInput().should('have.value', newName);
     }
 
+    public static manageEditedAdapter(newName: string, assetNameList = []) {
+        ConnectBtns.adapterConfigurationOptions().click();
+        ConnectBtns.manageAdapter().click();
+
+        ConnectBtns.managedResourceName().clear().type(newName);
+        ConnectBtns.managedResourceName().should('have.value', newName);
+
+        cy.get('mat-tree.asset-tree', { timeout: 10000 }).should('exist');
+        assetNameList.forEach(assetName => {
+            this.selectAssetTreeNode(assetName);
+        });
+
+        ConnectBtns.manageResourceSave().click();
+        ConnectBtns.manageResourceSave().should('not.exist');
+    }
+
     public static addMachineDataSimulator(
         name: string,
         persist: boolean = false,
diff --git a/ui/cypress/tests/connect/adapterWithAssets.spec.ts 
b/ui/cypress/tests/connect/adapterWithAssets.spec.ts
index ed12a5e409..0d6a84e1c1 100644
--- a/ui/cypress/tests/connect/adapterWithAssets.spec.ts
+++ b/ui/cypress/tests/connect/adapterWithAssets.spec.ts
@@ -78,19 +78,13 @@ describe('Creates a new adapter with a linked asset', () => 
{
         ConnectBtns.editAdapter().should('not.be.disabled');
         ConnectBtns.editAdapter().click();
 
+        ConnectUtils.manageEditedAdapter('Changed', [assetName1, assetName3]);
+
         // Go adapter settings page
         ConnectBtns.adapterSettingsNextBtn().click();
         ConnectBtns.configureSchemaNextBtn().click();
         ConnectBtns.configureFieldsNextBtn().click();
 
-        // Rename
-        ConnectUtils.renameAdapter('Changed');
-
-        // Deselect Asset 2
-        ConnectUtils.editAsset([assetName1]);
-
-        ConnectUtils.editAsset([assetName3]);
-
         ConnectBtns.storeEditAdapter().click();
 
         cy.dataCy('sp-connect-adapter-success-added', {
diff --git 
a/ui/src/app/connect/components/adapter-configuration/adapter-configuration.component.ts
 
b/ui/src/app/connect/components/adapter-configuration/adapter-configuration.component.ts
index 90e5c338da..56853582e3 100644
--- 
a/ui/src/app/connect/components/adapter-configuration/adapter-configuration.component.ts
+++ 
b/ui/src/app/connect/components/adapter-configuration/adapter-configuration.component.ts
@@ -25,7 +25,10 @@ import {
     ViewChild,
 } from '@angular/core';
 import { MatStep, MatStepLabel, MatStepper } from '@angular/material/stepper';
-import { AdapterDescription } from '@streampipes/platform-services';
+import {
+    AdapterDescription,
+    SpAssetTreeNode,
+} from '@streampipes/platform-services';
 import { ShepherdService } from '../../../services/tour/shepherd.service';
 import { Router } from '@angular/router';
 import { TranslatePipe, TranslateService } from '@ngx-translate/core';
@@ -98,6 +101,7 @@ export class AdapterConfigurationComponent implements 
OnInit, OnDestroy {
     myStepper: MatStepper;
     pageTitle = '';
     private pendingManageAdapterResult?: 
ObjectManageDialogResult<AdapterDescription>;
+    private readonly emptyAssets: SpAssetTreeNode[] = [];
 
     ngOnInit() {
         this.pageTitle = this.isEditMode
@@ -222,15 +226,22 @@ export class AdapterConfigurationComponent implements 
OnInit, OnDestroy {
     }
 
     get pendingSelectedAssets() {
-        return this.pendingManageAdapterResult?.selectedAssets ?? [];
+        return (
+            this.pendingManageAdapterResult?.selectedAssets ?? this.emptyAssets
+        );
     }
 
     get pendingDeselectedAssets() {
-        return this.pendingManageAdapterResult?.deselectedAssets ?? [];
+        return (
+            this.pendingManageAdapterResult?.deselectedAssets ??
+            this.emptyAssets
+        );
     }
 
     get pendingOriginalAssets() {
-        return this.pendingManageAdapterResult?.originalAssets ?? [];
+        return (
+            this.pendingManageAdapterResult?.originalAssets ?? this.emptyAssets
+        );
     }
 
     get shouldAddToAssets() {
diff --git 
a/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts 
b/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
index dc2d7db4ab..698b4d01d0 100644
--- 
a/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
+++ 
b/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
@@ -100,9 +100,9 @@ export class AdapterStartedDialog implements OnInit {
     /**
      * Assets selectedAsset to link the adapter tp
      */
-    @Input() selectedAssets: SpAssetTreeNode[];
-    @Input() deselectedAssets: SpAssetTreeNode[];
-    @Input() originalAssets: SpAssetTreeNode[];
+    @Input() selectedAssets: SpAssetTreeNode[] = [];
+    @Input() deselectedAssets: SpAssetTreeNode[] = [];
+    @Input() originalAssets: SpAssetTreeNode[] = [];
     @Input() permission?: Permission;
     @Input() addToAssets = true;
 
@@ -145,11 +145,13 @@ export class AdapterStartedDialog implements OnInit {
     deletedFromAssetText = '';
 
     ngOnInit() {
-        if (this.editMode) {
-            this.initAdapterUpdatePreflight();
-        } else {
-            this.addAdapter();
-        }
+        queueMicrotask(() => {
+            if (this.editMode) {
+                this.initAdapterUpdatePreflight();
+            } else {
+                this.addAdapter();
+            }
+        });
     }
 
     initAdapterUpdatePreflight(): void {
@@ -192,10 +194,14 @@ export class AdapterStartedDialog implements OnInit {
         this.adapterService.updateAdapter(this.adapter).subscribe({
             next: async status => {
                 if (status.success) {
-                    await this.persistManageMetadata();
-                    this.onAdapterReady(
-                        `Adapter ${this.adapter.name} was successfully updated 
and is available in the pipeline editor.`,
-                    );
+                    try {
+                        await this.persistManageMetadata();
+                        this.onAdapterReady(
+                            `Adapter ${this.adapter.name} was successfully 
updated and is available in the pipeline editor.`,
+                        );
+                    } catch (error) {
+                        this.onAssetSaveFailure(error);
+                    }
                 } else {
                     const errorLogMessage = this.getErrorLogMessage(status);
 
@@ -227,12 +233,12 @@ export class AdapterStartedDialog implements OnInit {
                 if (status.success) {
                     const adapterElementId = status.notifications[0].title;
                     this.adapterElementId = adapterElementId;
-                    this.adapterElementId = adapterElementId;
                     if (this.saveInDataLake) {
                         this.startSaveInDataLakePipeline(adapterElementId);
                     } else {
-                        this.startAdapter(adapterElementId, true);
-                        this.addToAsset();
+                        this.startAdapter(adapterElementId, true, () =>
+                            this.addToAsset(),
+                        );
                     }
                 } else {
                     const errorMsg: SpLogMessage =
@@ -261,7 +267,11 @@ export class AdapterStartedDialog implements OnInit {
         };
     }
 
-    startAdapter(adapterElementId: string, showPreview = false) {
+    startAdapter(
+        adapterElementId: string,
+        showPreview = false,
+        afterStart?: () => Promise<void>,
+    ): void {
         const successMessage = this.translateService.instant(
             'Your new data stream is now available in the pipeline editor.',
         );
@@ -281,19 +291,46 @@ export class AdapterStartedDialog implements OnInit {
             );
             this.adapterService
                 .startAdapterByElementId(adapterElementId)
-                .subscribe(
-                    () => {
-                        this.onAdapterReady(successMessage, showPreview);
+                .subscribe({
+                    next: () => {
+                        void this.finishAdapterStart(
+                            successMessage,
+                            showPreview,
+                            afterStart,
+                        );
                     },
-                    error => {
+                    error: error => {
                         this.onAdapterFailure(error.error);
                     },
-                );
+                });
         } else {
-            this.onAdapterReady(successMessage, false);
+            void this.finishAdapterStart(successMessage, false, afterStart);
+        }
+    }
+
+    private async finishAdapterStart(
+        successMessage: string,
+        showPreview: boolean,
+        afterStart?: () => Promise<void>,
+    ): Promise<void> {
+        try {
+            await afterStart?.();
+            this.onAdapterReady(successMessage, showPreview);
+        } catch (error) {
+            this.onAssetSaveFailure(error);
         }
     }
 
+    private onAssetSaveFailure(error: unknown): void {
+        this.onAdapterFailure({
+            cause: `${error}`,
+            detail: '',
+            fullStackTrace: `${error}`,
+            level: 'ERROR',
+            title: 'Could not save asset links',
+        });
+    }
+
     onAdapterFailure(adapterErrorMessage: SpLogMessage) {
         this.adapterInstalled = true;
 
@@ -322,30 +359,27 @@ export class AdapterStartedDialog implements OnInit {
 
     async addToAsset(pipelineId = ''): Promise<void> {
         let linkageData: LinkageData[];
-        try {
-            if (!this.editMode) {
-                const adapter = await this.getAdapter();
-                linkageData = this.createLinkageData(adapter);
-
-                if (this.saveInDataLake && pipelineId !== '') {
-                    await this.addDataLakeLinkageData(
-                        adapter,
-                        linkageData,
-                        pipelineId,
-                    );
-                }
-            } else {
-                linkageData = this.createLinkageData(this.adapter);
-            }
 
-            if (this.addToAssets) {
-                await this.saveAssets(linkageData);
+        if (!this.editMode) {
+            const adapter = await this.getAdapter();
+            linkageData = this.createLinkageData(adapter);
+
+            if (this.saveInDataLake && pipelineId !== '') {
+                await this.addDataLakeLinkageData(
+                    adapter,
+                    linkageData,
+                    pipelineId,
+                );
             }
+        } else {
+            linkageData = this.createLinkageData(this.adapter);
+        }
 
-            this.setSuccessMessage();
-        } catch (err) {
-            console.error('Error in addToAsset:', err);
+        if (this.addToAssets) {
+            await this.saveAssets(linkageData);
         }
+
+        this.setSuccessMessage();
     }
 
     private async getAdapter(): Promise<AdapterDescription> {
@@ -463,8 +497,9 @@ export class AdapterStartedDialog implements OnInit {
                             pipelineOperationStatus => {
                                 this.pipelineOperationStatus =
                                     pipelineOperationStatus;
-                                this.startAdapter(adapterElementId, true);
-                                this.addToAsset(pipelineId);
+                                this.startAdapter(adapterElementId, true, () =>
+                                    this.addToAsset(pipelineId),
+                                );
                             },
                             error => {
                                 this.onAdapterFailure(error.error);

Reply via email to