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

zehnder pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to refs/heads/dev by this push:
     new 57cd56c079 feat: Add e2e to test asset filters (#3976)
57cd56c079 is described below

commit 57cd56c07915acea656f7e179e523570ef5cc4ad
Author: Philipp Zehnder <[email protected]>
AuthorDate: Thu Nov 27 11:33:31 2025 +0100

    feat: Add e2e to test asset filters (#3976)
---
 .../apache/streampipes/rest/ResetManagement.java   |   3 +-
 ui/cypress/support/builder/AssetBuilder.ts         |  82 ++++++
 ui/cypress/support/model/Asset.ts                  |  27 ++
 ui/cypress/support/utils/DashboardUtils.ts         |  22 ++
 ui/cypress/support/utils/asset/AssetBtns.ts        |  26 ++
 ui/cypress/support/utils/asset/AssetUtils.ts       |  59 ++++-
 .../utils/configuration/ConfigurationUtils.ts      |   8 +-
 .../support/utils/configuration/SiteUtils.ts       |   2 +-
 .../utils/dataExplorer/DataExplorerUtils.ts        |  22 +-
 ui/cypress/support/utils/filter/FilterBtns.ts      |  63 +++++
 ui/cypress/support/utils/filter/FilterUtils.ts     |  97 +++++++
 .../tests/assetManagement/assetFilterTest.spec.ts  | 282 +++++++++++++++++++++
 ui/cypress/tests/connect/adapterWithAssets.spec.ts |  10 +-
 .../dataExplorer/addAssetToDashboard.smoke.spec.ts |  12 +-
 .../dataExplorer/addAssetsToDataView.smoke.spec.ts |  11 +-
 ui/cypress/tests/pipeline/pipelineAsset.spec.ts    |  10 +-
 .../testAddAssetOnResourceCreation.ts              |   4 +-
 .../userManagement/testUserRoleAssets.spec.ts      |   4 +-
 ...asset-browser-filter-asset-model.component.html |   2 +
 .../asset-browser-filter-labels.component.html     |   2 +
 .../asset-browser-filter-outer.component.html      |   1 +
 .../asset-browser-filter-sites.component.html      |   2 +
 .../asset-browser-filter-type.component.html       |   2 +
 .../asset-browser-filter.component.html            |  14 +-
 .../asset-browser-toolbar.component.html           |   1 +
 .../asset-link-configuration.component.html        |   1 +
 .../asset-details-basics.component.html            |   3 +
 .../asset-details-labels.component.html            |   9 +-
 .../asset-details-site.component.html              |   7 +-
 .../asset-selection-panel.component.html           |   9 +
 30 files changed, 762 insertions(+), 35 deletions(-)

diff --git 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/ResetManagement.java
 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/ResetManagement.java
index e5804a563c..03b2399110 100644
--- 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/ResetManagement.java
+++ 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/ResetManagement.java
@@ -186,7 +186,8 @@ public class ResetManagement {
   private static void clearGenericStorage() {
     var appDocTypesToDelete = List.of(
         "asset-management",
-        "asset-sites"
+        "asset-sites",
+        "sp-labels"
     );
     var genericStorage = StorageDispatcher.INSTANCE.getNoSqlStore()
                                                    .getGenericStorage();
diff --git a/ui/cypress/support/builder/AssetBuilder.ts 
b/ui/cypress/support/builder/AssetBuilder.ts
new file mode 100644
index 0000000000..f73ce39d1f
--- /dev/null
+++ b/ui/cypress/support/builder/AssetBuilder.ts
@@ -0,0 +1,82 @@
+/*
+ *  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.
+ *
+ */
+
+import { Asset } from '../model/Asset';
+import { Isa95Type } from 
'../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
+
+export class AssetBuilder {
+    asset: Asset;
+
+    constructor() {
+        this.asset = new Asset();
+        this.asset.labels = [];
+        this.asset.subAssets = [];
+        this.asset.assetType = 'OTHER';
+    }
+
+    public static create(name: string) {
+        const builder = new AssetBuilder();
+        builder.setName(name);
+        return builder;
+    }
+
+    public setName(name: string) {
+        this.asset.name = name;
+        return this;
+    }
+
+    public setAssetType(type: Isa95Type) {
+        this.asset.assetType = type;
+        return this;
+    }
+
+    public addLabel(label: string) {
+        if (!this.asset.labels) {
+            this.asset.labels = [];
+        }
+        this.asset.labels.push(label);
+        return this;
+    }
+
+    public setLabels(labels: string[]) {
+        this.asset.labels = labels || [];
+        return this;
+    }
+
+    public setSite(site: string) {
+        this.asset.site = site;
+        return this;
+    }
+
+    public addSubAsset(subAsset: Asset) {
+        if (!this.asset.subAssets) {
+            this.asset.subAssets = [];
+        }
+        this.asset.subAssets.push(subAsset);
+        return this;
+    }
+
+    public addSubAssetBuilder(builder: AssetBuilder) {
+        this.addSubAsset(builder.build());
+        return this;
+    }
+
+    public build() {
+        return this.asset;
+    }
+}
diff --git a/ui/cypress/support/model/Asset.ts 
b/ui/cypress/support/model/Asset.ts
new file mode 100644
index 0000000000..376fe61549
--- /dev/null
+++ b/ui/cypress/support/model/Asset.ts
@@ -0,0 +1,27 @@
+/*
+ *  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.
+ *
+ */
+
+import { Isa95Type } from 
'../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
+
+export class Asset {
+    name: string;
+    assetType: Isa95Type;
+    labels: string[];
+    site?: string;
+    subAssets: Asset[];
+}
diff --git a/ui/cypress/support/utils/DashboardUtils.ts 
b/ui/cypress/support/utils/DashboardUtils.ts
index 46268b4173..98e28538b7 100644
--- a/ui/cypress/support/utils/DashboardUtils.ts
+++ b/ui/cypress/support/utils/DashboardUtils.ts
@@ -16,6 +16,8 @@
  *
  */
 
+import { ConnectBtns } from './connect/ConnectBtns';
+
 export class DashboardUtils {
     public static goToDashboard() {
         cy.visit('#/dashboard');
@@ -117,4 +119,24 @@ export class DashboardUtils {
 
         DashboardUtils.removeWidgetFromDashboard(dashboardName);
     }
+
+    public static checkAmountOfDashboards(amount: number) {
+        if (amount === 0) {
+            // The wait is needed because the default value is the 
no-table-entries element.
+            // It must be waited till the data is loaded. Once a better 
solution is found, this can be removed.
+            cy.wait(1000);
+            cy.dataCy('no-table-entries').should('be.visible');
+        } else {
+            ConnectBtns.moreOptions().should('have.length', amount);
+        }
+    }
+
+    public static checkInList(resources: string[]) {
+        this.checkAmountOfDashboards(resources.length);
+        resources.forEach(resource => {
+            cy.dataCy('dashboard-table-overview')
+                .contains(resource)
+                .should('exist');
+        });
+    }
 }
diff --git a/ui/cypress/support/utils/asset/AssetBtns.ts 
b/ui/cypress/support/utils/asset/AssetBtns.ts
index d958a3fe14..8248d1eae8 100644
--- a/ui/cypress/support/utils/asset/AssetBtns.ts
+++ b/ui/cypress/support/utils/asset/AssetBtns.ts
@@ -16,6 +16,8 @@
  *
  */
 
+import { Isa95Type } from 
'../../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
+
 export class AssetBtns {
     public static createAssetBtn() {
         return cy.dataCy('create-new-asset-button', { timeout: 10000 });
@@ -25,6 +27,30 @@ export class AssetBtns {
         return cy.dataCy('asset-name', { timeout: 10000 });
     }
 
+    public static assetTypeSelect() {
+        return cy.dataCy('asset-type-select', { timeout: 10000 });
+    }
+
+    public static assetTypeSelectOption(type: Isa95Type) {
+        return cy.dataCy(`option-${type}`, { timeout: 10000 });
+    }
+
+    public static siteSelect() {
+        return cy.dataCy('asset-site-select', { timeout: 10000 });
+    }
+
+    public static siteSelectOption(site: string) {
+        return cy.dataCy(`option-${site}`, { timeout: 10000 });
+    }
+
+    public static labelSelect() {
+        return cy.dataCy('asset-label-input', { timeout: 10000 });
+    }
+
+    public static labelSelectOption(label: string) {
+        return cy.dataCy(`option-${label}`, { timeout: 10000 });
+    }
+
     public static saveAssetBtn() {
         return cy.dataCy('save-asset', { timeout: 10000 });
     }
diff --git a/ui/cypress/support/utils/asset/AssetUtils.ts 
b/ui/cypress/support/utils/asset/AssetUtils.ts
index b40211b4c4..d05459befd 100644
--- a/ui/cypress/support/utils/asset/AssetUtils.ts
+++ b/ui/cypress/support/utils/asset/AssetUtils.ts
@@ -19,6 +19,9 @@
 import { AssetBtns } from './AssetBtns';
 import { ConnectUtils } from '../connect/ConnectUtils';
 import { GeneralUtils } from '../GeneralUtils';
+import { Asset } from '../../model/Asset';
+import { Isa95Type } from 
'../../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
+import { AssetBuilder } from '../../builder/AssetBuilder';
 
 export class AssetUtils {
     public static goToAssets() {
@@ -30,18 +33,58 @@ export class AssetUtils {
         AssetBtns.goBackToOverviewBtn().click();
     }
 
-    public static addNewAsset(assetName: string) {
+    public static addAndSaveAsset(asset: Asset) {
+        AssetUtils.addNewAsset(asset);
+
+        AssetBtns.saveAssetBtn().click();
+        AssetBtns.createAssetBtn().should('be.visible');
+    }
+
+    public static addNewAsset(asset: Asset) {
         AssetBtns.createAssetBtn().click();
-        AssetBtns.assetNameInput().clear();
-        AssetBtns.assetNameInput().type(assetName);
+        AssetBtns.assetNameInput().clear().type(asset.name);
         AssetBtns.createAssetPanelBtn().click();
+
+        this.selectAssetType(asset.assetType);
+        if (asset.site) {
+            this.selectSite(asset.site);
+        }
+        if (asset.labels.length > 0) {
+            this.addLabels(asset.labels);
+        }
+
+        for (const subAsset of asset.subAssets) {
+            this.clickAddSubAssetBtn(asset.name);
+            this.selectSubAsset('New\\ Asset');
+            AssetBtns.assetNameInput().clear().type(subAsset.name);
+            this.selectAssetType(subAsset.assetType);
+            this.addLabels(subAsset.labels);
+        }
     }
 
-    public static addAndSaveAsset(assetName: string) {
-        AssetUtils.addNewAsset(assetName);
+    public static clickAddSubAssetBtn(assetName: string) {
+        cy.dataCy(`add-asset-${assetName}`).click();
+    }
 
-        AssetBtns.saveAssetBtn().click();
-        AssetBtns.createAssetBtn().should('be.visible');
+    public static selectSubAsset(assetName: string) {
+        cy.dataCy(`select-asset-${assetName}`).click();
+    }
+
+    public static addLabels(labels: string[]) {
+        AssetBtns.labelSelect().click();
+        for (const label of labels) {
+            AssetBtns.labelSelectOption(label).click();
+        }
+    }
+
+    public static selectSite(site: string) {
+        AssetBtns.siteSelect().click();
+        AssetBtns.siteSelectOption(site).click();
+    }
+
+    public static selectAssetType(type: Isa95Type) {
+        AssetBtns.assetTypeSelect().click();
+        AssetBtns.assetTypeSelectOption(type).click();
     }
 
     public static openManageAssetLinks() {
@@ -130,7 +173,7 @@ export class AssetUtils {
         // Create new asset from adapters
         AssetUtils.goToAssets();
 
-        AssetUtils.addNewAsset(assetName);
+        AssetUtils.addNewAsset(AssetBuilder.create(assetName).build());
 
         AssetBtns.assetLinksTab().click();
         AssetUtils.openManageAssetLinks();
diff --git a/ui/cypress/support/utils/configuration/ConfigurationUtils.ts 
b/ui/cypress/support/utils/configuration/ConfigurationUtils.ts
index 62a0ad65e3..2c06edea38 100644
--- a/ui/cypress/support/utils/configuration/ConfigurationUtils.ts
+++ b/ui/cypress/support/utils/configuration/ConfigurationUtils.ts
@@ -33,10 +33,12 @@ export class ConfigurationUtils {
         cy.visit('#/configuration/labels');
     }
 
-    public static addNewLabel(name: string, description: string) {
+    public static addNewLabel(name: string, description: string = '') {
         cy.dataCy('new-label-button').click();
-        cy.dataCy('label-name').type(name);
-        cy.dataCy('label-description').type(description);
+        cy.dataCy('label-name').clear().type(name);
+        if (description !== '') {
+            cy.dataCy('label-description').type(description);
+        }
         cy.dataCy('save-label-button').click();
     }
 
diff --git a/ui/cypress/support/utils/configuration/SiteUtils.ts 
b/ui/cypress/support/utils/configuration/SiteUtils.ts
index 60252bbda3..ec20e97530 100644
--- a/ui/cypress/support/utils/configuration/SiteUtils.ts
+++ b/ui/cypress/support/utils/configuration/SiteUtils.ts
@@ -47,7 +47,7 @@ export class SiteUtils {
         cy.dataCy('sites-location-features-button').click();
     }
 
-    public static createNewSite(name: string, areas: string[]): void {
+    public static createNewSite(name: string, areas: string[] = []): void {
         cy.dataCy(SiteUtils.BUTTON_MANAGE_SITES).click();
         cy.dataCy(SiteUtils.INPUT_SITE_DIALOG_SITE_INPUT, { timeout: 2000 })
             .clear()
diff --git a/ui/cypress/support/utils/dataExplorer/DataExplorerUtils.ts 
b/ui/cypress/support/utils/dataExplorer/DataExplorerUtils.ts
index c3d8557890..ec053df06b 100644
--- a/ui/cypress/support/utils/dataExplorer/DataExplorerUtils.ts
+++ b/ui/cypress/support/utils/dataExplorer/DataExplorerUtils.ts
@@ -163,7 +163,7 @@ export class DataExplorerUtils {
         cy.wait(1000);
     }
 
-    public static addAssetsToDashboard(assetNameList) {
+    public static addAssetsToDashboard(assetNameList: string[]) {
         cy.dataCy('sp-show-dashboard-asset-checkbox')
             .find('input[type="checkbox"]')
             .then($checkbox => {
@@ -174,9 +174,17 @@ export class DataExplorerUtils {
 
         cy.get('mat-tree.asset-tree', { timeout: 10000 }).should('exist');
         assetNameList.forEach(assetName => {
+            const assetHierarchy = assetName.split('.');
+            const lastElement = assetHierarchy[assetHierarchy.length - 1];
+            const firstElements = assetHierarchy.slice(0, -1);
+
+            firstElements.forEach(el => {
+                cy.dataCy(`toggle-${el}`).click();
+            });
+
             cy.get('mat-tree.asset-tree')
                 .find('.mat-tree-node')
-                .contains(assetName)
+                .contains(lastElement)
                 .click();
         });
     }
@@ -187,6 +195,16 @@ export class DataExplorerUtils {
         DataExplorerUtils.saveDataView();
     }
 
+    public static createNewDashboardWithAssetLinks(
+        name: string,
+        assetNameList: string[],
+    ) {
+        DataExplorerUtils.goToDashboard();
+        DataExplorerUtils.addNewDashboard(name);
+        DataExplorerUtils.addAssetsToDashboard(assetNameList);
+        DataExplorerUtils.saveDataView();
+    }
+
     public static addNewDashboard(name: string) {
         DataExplorerBtns.newDashboardDialogBtn().click();
         cy.dataCy('data-view-name').type(name);
diff --git a/ui/cypress/support/utils/filter/FilterBtns.ts 
b/ui/cypress/support/utils/filter/FilterBtns.ts
new file mode 100644
index 0000000000..0ad543e7eb
--- /dev/null
+++ b/ui/cypress/support/utils/filter/FilterBtns.ts
@@ -0,0 +1,63 @@
+/*
+ *  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.
+ *
+ */
+
+export class FilterBtns {
+    public static filterBtn() {
+        return cy.dataCy('filter-button', { timeout: 10000 });
+    }
+
+    public static resetFiltersBtn() {
+        return cy.dataCy('reset-filters-btn', { timeout: 10000 });
+    }
+
+    public static filtersDeselectAssets() {
+        return cy.dataCy('filters-deselect-Assets', { timeout: 10000 });
+    }
+
+    public static filtersAssetSelect() {
+        return cy.dataCy('filters-asset-select', { timeout: 10000 });
+    }
+
+    public static filtersDeselectSites() {
+        return cy.dataCy('filters-deselect-Sites', { timeout: 10000 });
+    }
+
+    public static filtersSitesSelect() {
+        return cy.dataCy('filters-sites-select', { timeout: 10000 });
+    }
+
+    public static filtersDeselectLabels() {
+        return cy.dataCy('filters-deselect-Labels', { timeout: 10000 });
+    }
+
+    public static filtersLabelsSelect() {
+        return cy.dataCy('filters-labels-select', { timeout: 10000 });
+    }
+
+    public static filtersDeselectTypes() {
+        return cy.dataCy('filters-deselect-Type', { timeout: 10000 });
+    }
+
+    public static filtersTypesSelect() {
+        return cy.dataCy('filters-types-select', { timeout: 10000 });
+    }
+
+    public static applyFiltersBtn() {
+        return cy.dataCy('apply-filters-btn', { timeout: 10000 });
+    }
+}
diff --git a/ui/cypress/support/utils/filter/FilterUtils.ts 
b/ui/cypress/support/utils/filter/FilterUtils.ts
new file mode 100644
index 0000000000..8b3ddf4fc6
--- /dev/null
+++ b/ui/cypress/support/utils/filter/FilterUtils.ts
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ *
+ */
+
+import { FilterBtns } from './FilterBtns';
+
+export class FilterUtils {
+    public static clearFilter() {
+        FilterBtns.filterBtn().click();
+        FilterBtns.resetFiltersBtn().click();
+    }
+
+    public static selectAssetFilter(name: string) {
+        cy.dataCy(`asset-option-${name}`).click();
+    }
+
+    public static selectSiteFilter(name: string) {
+        cy.dataCy(`site-option-${name}`).click();
+    }
+
+    public static selectLabelFilter(name: string) {
+        cy.dataCy(`label-option-${name}`).click();
+    }
+
+    public static selectTypeFilter(name: string) {
+        cy.dataCy(`type-option-${name}`).click();
+    }
+
+    public static filterAssets(assetNames: string[]) {
+        FilterBtns.filterBtn().click();
+        FilterBtns.filtersDeselectAssets().click();
+        FilterBtns.filtersAssetSelect().click();
+        assetNames.forEach(assetName => {
+            this.selectAssetFilter(assetName);
+        });
+
+        // click somewhere else to close the dropdown
+        cy.get('body').click(0, 0);
+        FilterBtns.applyFiltersBtn().click();
+    }
+
+    public static filterSites(siteNames: string[]) {
+        FilterBtns.filterBtn().click();
+        FilterBtns.filtersDeselectSites().click();
+        FilterBtns.filtersSitesSelect().click();
+
+        siteNames.forEach(siteName => {
+            this.selectSiteFilter(siteName);
+        });
+
+        // click somewhere else to close the dropdown
+        cy.get('body').click(0, 0);
+        FilterBtns.applyFiltersBtn().click();
+    }
+
+    public static filterLabels(siteNames: string[]) {
+        FilterBtns.filterBtn().click();
+        FilterBtns.filtersDeselectLabels().click();
+        FilterBtns.filtersLabelsSelect().click();
+
+        siteNames.forEach(siteName => {
+            this.selectLabelFilter(siteName);
+        });
+
+        // click somewhere else to close the dropdown
+        cy.get('body').click(0, 0);
+        FilterBtns.applyFiltersBtn().click();
+    }
+
+    public static filterTypes(typeNames: string[]) {
+        FilterBtns.filterBtn().click();
+        FilterBtns.filtersDeselectTypes().click();
+        FilterBtns.filtersTypesSelect().click();
+
+        typeNames.forEach(siteName => {
+            this.selectTypeFilter(siteName);
+        });
+
+        // click somewhere else to close the dropdown
+        cy.get('body').click(0, 0);
+        FilterBtns.applyFiltersBtn().click();
+    }
+}
diff --git a/ui/cypress/tests/assetManagement/assetFilterTest.spec.ts 
b/ui/cypress/tests/assetManagement/assetFilterTest.spec.ts
new file mode 100644
index 0000000000..49456a0cdd
--- /dev/null
+++ b/ui/cypress/tests/assetManagement/assetFilterTest.spec.ts
@@ -0,0 +1,282 @@
+/*
+ * 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.
+ *
+ */
+
+import { AssetUtils } from '../../support/utils/asset/AssetUtils';
+import { DashboardUtils } from '../../support/utils/DashboardUtils';
+import { DataExplorerUtils } from 
'../../support/utils/dataExplorer/DataExplorerUtils';
+import { AssetBuilder } from '../../support/builder/AssetBuilder';
+import { ConfigurationUtils } from 
'../../support/utils/configuration/ConfigurationUtils';
+import { SiteUtils } from '../../support/utils/configuration/SiteUtils';
+import { FilterUtils } from '../../support/utils/filter/FilterUtils';
+
+describe('Test asset filters', () => {
+    const label1 = 'label1';
+    const label2 = 'label2';
+    const label3 = 'label3';
+
+    const site1 = 'site1';
+    const site2 = 'site2';
+    const site3 = 'site3';
+
+    const asset1 = AssetBuilder.create('asset-1_0')
+        .addLabel(label1)
+        .setSite(site1)
+        .setAssetType('PRODUCTION_LINE')
+        .addSubAsset(
+            AssetBuilder.create('asset-1_1')
+                .addLabel(label2)
+                .setAssetType('WORK_CELL')
+                .build(),
+        )
+        .addSubAsset(
+            AssetBuilder.create('asset-1_2')
+                .addLabel(label3)
+                .setAssetType('WORK_CELL')
+                .build(),
+        )
+        .build();
+
+    const asset2 = AssetBuilder.create('asset-2_0')
+        .addLabel(label1)
+        .setSite(site2)
+        .setAssetType('PRODUCTION_LINE')
+        .addSubAsset(
+            AssetBuilder.create('asset-2_1')
+                .addLabel(label2)
+                .setAssetType('WORK_CELL')
+                .build(),
+        )
+        .addSubAsset(
+            AssetBuilder.create('asset-2_2')
+                .addLabel(label3)
+                .setAssetType('WORK_CELL')
+                .build(),
+        )
+        .build();
+
+    const asset3 = AssetBuilder.create('asset-3_0')
+        .addLabel(label1)
+        .setSite(site3)
+        .setAssetType('PRODUCTION_LINE')
+        .addSubAsset(
+            AssetBuilder.create('asset-3_1')
+                .addLabel(label2)
+                .setAssetType('WORK_CELL')
+                .build(),
+        )
+        .addSubAsset(
+            AssetBuilder.create('asset-3_2')
+                .addLabel(label3)
+                .setAssetType('WORK_CELL')
+                .build(),
+        )
+        .build();
+
+    beforeEach('Setup Test', () => {
+        cy.initStreamPipesTest();
+        prepareLabels();
+        prepareSites();
+        prepareAssets();
+        prepareDashboards();
+        DashboardUtils.goToDashboard();
+        DashboardUtils.checkAmountOfDashboards(9);
+        DashboardUtils.checkInList([
+            'dashboard-1_0',
+            'dashboard-1_1',
+            'dashboard-1_2',
+            'dashboard-2_0',
+            'dashboard-2_1',
+            'dashboard-2_2',
+            'dashboard-3_0',
+            'dashboard-3_1',
+            'dashboard-3_2',
+        ]);
+
+        // This is currently required because the assets are only loaded on 
page load
+        cy.reload();
+    });
+
+    it('Perform Test', () => {
+        // Select one asset
+        FilterUtils.clearFilter();
+        FilterUtils.filterAssets(['asset-1_0']);
+
+        DashboardUtils.checkInList([
+            'dashboard-1_0',
+            'dashboard-1_1',
+            'dashboard-1_2',
+        ]);
+
+        // Select asset 1 & asset 2
+        FilterUtils.clearFilter();
+        FilterUtils.filterAssets(['asset-1_0', 'asset-2_0']);
+        DashboardUtils.checkInList([
+            'dashboard-1_0',
+            'dashboard-1_1',
+            'dashboard-1_2',
+            'dashboard-2_0',
+            'dashboard-2_1',
+            'dashboard-2_2',
+        ]);
+
+        // Select site 1
+        FilterUtils.clearFilter();
+        FilterUtils.filterSites(['site1']);
+        DashboardUtils.checkInList([
+            'dashboard-1_0',
+            'dashboard-1_1',
+            'dashboard-1_2',
+        ]);
+
+        // Select site 1 & site 2
+        FilterUtils.clearFilter();
+        FilterUtils.filterSites(['site1', 'site2']);
+        DashboardUtils.checkInList([
+            'dashboard-1_0',
+            'dashboard-1_1',
+            'dashboard-1_2',
+            'dashboard-2_0',
+            'dashboard-2_1',
+            'dashboard-2_2',
+        ]);
+
+        // Select label 3
+        FilterUtils.clearFilter();
+        FilterUtils.filterLabels(['label3']);
+
+        DashboardUtils.checkInList([
+            'dashboard-1_2',
+            'dashboard-2_2',
+            'dashboard-3_2',
+        ]);
+
+        // Select label 2 & 3
+        FilterUtils.clearFilter();
+        FilterUtils.filterLabels(['label2', 'label3']);
+
+        DashboardUtils.checkInList([
+            'dashboard-1_1',
+            'dashboard-1_2',
+            'dashboard-2_1',
+            'dashboard-2_2',
+            'dashboard-3_1',
+            'dashboard-3_2',
+        ]);
+
+        // Select type PRODUCTION_LINE
+        FilterUtils.clearFilter();
+        FilterUtils.filterTypes(['PRODUCTION_LINE']);
+
+        DashboardUtils.checkInList([
+            'dashboard-1_0',
+            'dashboard-2_0',
+            'dashboard-3_0',
+        ]);
+
+        FilterUtils.clearFilter();
+        FilterUtils.filterTypes(['WORK_CELL']);
+
+        DashboardUtils.checkInList([
+            'dashboard-1_1',
+            'dashboard-1_2',
+            'dashboard-2_1',
+            'dashboard-2_2',
+            'dashboard-3_1',
+            'dashboard-3_2',
+        ]);
+
+        // Select asset 1 & site 1 & label 2
+        FilterUtils.clearFilter();
+        FilterUtils.filterAssets(['asset-1_0']);
+        FilterUtils.filterSites(['site1']);
+        FilterUtils.filterLabels(['label2']);
+
+        DashboardUtils.checkInList(['dashboard-1_1']);
+
+        AssetUtils.goToAssets();
+
+        FilterUtils.clearFilter();
+        FilterUtils.filterAssets(['asset-1_0']);
+        AssetUtils.checkAmountOfAssets(1);
+
+        FilterUtils.clearFilter();
+        FilterUtils.filterLabels(['label2']);
+        AssetUtils.checkAmountOfAssets(3);
+
+        FilterUtils.clearFilter();
+        FilterUtils.filterTypes(['PRODUCTION_LINE']);
+        AssetUtils.checkAmountOfAssets(3);
+
+        FilterUtils.clearFilter();
+        FilterUtils.filterSites(['site2']);
+        AssetUtils.checkAmountOfAssets(1);
+    });
+
+    function prepareAssets() {
+        AssetUtils.goToAssets();
+        AssetUtils.addAndSaveAsset(asset1);
+        AssetUtils.addAndSaveAsset(asset2);
+        AssetUtils.addAndSaveAsset(asset3);
+    }
+
+    function prepareDashboards() {
+        DataExplorerUtils.createNewDashboardWithAssetLinks('dashboard-1_0', [
+            'asset-1_0',
+        ]);
+        DataExplorerUtils.createNewDashboardWithAssetLinks('dashboard-1_1', [
+            'asset-1_0.asset-1_1',
+        ]);
+        DataExplorerUtils.createNewDashboardWithAssetLinks('dashboard-1_2', [
+            'asset-1_0.asset-1_2',
+        ]);
+
+        DataExplorerUtils.createNewDashboardWithAssetLinks('dashboard-2_0', [
+            'asset-2_0',
+        ]);
+        DataExplorerUtils.createNewDashboardWithAssetLinks('dashboard-2_1', [
+            'asset-2_0.asset-2_1',
+        ]);
+        DataExplorerUtils.createNewDashboardWithAssetLinks('dashboard-2_2', [
+            'asset-2_0.asset-2_2',
+        ]);
+
+        DataExplorerUtils.createNewDashboardWithAssetLinks('dashboard-3_0', [
+            'asset-3_0',
+        ]);
+        DataExplorerUtils.createNewDashboardWithAssetLinks('dashboard-3_1', [
+            'asset-3_0.asset-3_1',
+        ]);
+        DataExplorerUtils.createNewDashboardWithAssetLinks('dashboard-3_2', [
+            'asset-3_0.asset-3_2',
+        ]);
+    }
+
+    function prepareLabels() {
+        ConfigurationUtils.goToLabelConfiguration();
+        ConfigurationUtils.addNewLabel(label1);
+        ConfigurationUtils.addNewLabel(label2);
+        ConfigurationUtils.addNewLabel(label3);
+    }
+
+    function prepareSites() {
+        ConfigurationUtils.goToSitesConfiguration();
+        SiteUtils.createNewSite(site1);
+        SiteUtils.createNewSite(site2);
+        SiteUtils.createNewSite(site3);
+    }
+});
diff --git a/ui/cypress/tests/connect/adapterWithAssets.spec.ts 
b/ui/cypress/tests/connect/adapterWithAssets.spec.ts
index c69d7d71b8..6a12fc9737 100644
--- a/ui/cypress/tests/connect/adapterWithAssets.spec.ts
+++ b/ui/cypress/tests/connect/adapterWithAssets.spec.ts
@@ -21,6 +21,7 @@ import { AdapterBuilder } from 
'../../support/builder/AdapterBuilder';
 import { AssetUtils } from '../../support/utils/asset/AssetUtils';
 import { ConnectBtns } from '../../support/utils/connect/ConnectBtns';
 import { AssetBtns } from '../../support/utils/asset/AssetBtns';
+import { AssetBuilder } from '../../support/builder/AssetBuilder';
 
 describe('Creates a new adapter with a linked asset', () => {
     const assetName1 = 'TestAsset1';
@@ -35,9 +36,12 @@ describe('Creates a new adapter with a linked asset', () => {
     beforeEach('Setup Test', () => {
         cy.initStreamPipesTest();
         AssetUtils.goToAssets();
-        AssetUtils.addAndSaveAsset(assetName3);
-        AssetUtils.addAndSaveAsset(assetName2);
-        AssetUtils.addAndSaveAsset(assetName1);
+        const asset1 = AssetBuilder.create(assetName1).build();
+        const asset2 = AssetBuilder.create(assetName2).build();
+        const asset3 = AssetBuilder.create(assetName3).build();
+        AssetUtils.addAndSaveAsset(asset3);
+        AssetUtils.addAndSaveAsset(asset2);
+        AssetUtils.addAndSaveAsset(asset1);
     });
 
     it('Add Assets during Adapter generation', () => {
diff --git a/ui/cypress/tests/dataExplorer/addAssetToDashboard.smoke.spec.ts 
b/ui/cypress/tests/dataExplorer/addAssetToDashboard.smoke.spec.ts
index 073243033a..665a500d88 100644
--- a/ui/cypress/tests/dataExplorer/addAssetToDashboard.smoke.spec.ts
+++ b/ui/cypress/tests/dataExplorer/addAssetToDashboard.smoke.spec.ts
@@ -18,6 +18,7 @@
 import { AssetBtns } from '../../support/utils/asset/AssetBtns';
 import { AssetUtils } from '../../support/utils/asset/AssetUtils';
 import { DataExplorerUtils } from 
'../../support/utils/dataExplorer/DataExplorerUtils';
+import { AssetBuilder } from '../../support/builder/AssetBuilder';
 
 describe('Test add Assets To Dashboard', () => {
     const assetName1 = 'TestAsset1';
@@ -26,9 +27,14 @@ describe('Test add Assets To Dashboard', () => {
     beforeEach('Setup Test', () => {
         cy.initStreamPipesTest();
         AssetUtils.goToAssets();
-        AssetUtils.addAndSaveAsset(assetName3);
-        AssetUtils.addAndSaveAsset(assetName2);
-        AssetUtils.addAndSaveAsset(assetName1);
+
+        const asset1 = AssetBuilder.create(assetName1).build();
+        const asset2 = AssetBuilder.create(assetName2).build();
+        const asset3 = AssetBuilder.create(assetName3).build();
+
+        AssetUtils.addAndSaveAsset(asset3);
+        AssetUtils.addAndSaveAsset(asset2);
+        AssetUtils.addAndSaveAsset(asset1);
         DataExplorerUtils.loadDataIntoDataLake('datalake/sample.csv');
     });
 
diff --git a/ui/cypress/tests/dataExplorer/addAssetsToDataView.smoke.spec.ts 
b/ui/cypress/tests/dataExplorer/addAssetsToDataView.smoke.spec.ts
index 4c8637a846..6fd7d79c2f 100644
--- a/ui/cypress/tests/dataExplorer/addAssetsToDataView.smoke.spec.ts
+++ b/ui/cypress/tests/dataExplorer/addAssetsToDataView.smoke.spec.ts
@@ -18,6 +18,7 @@
 
 import { AssetUtils } from '../../support/utils/asset/AssetUtils';
 import { DataExplorerUtils } from 
'../../support/utils/dataExplorer/DataExplorerUtils';
+import { AssetBuilder } from '../../support/builder/AssetBuilder';
 
 describe('Creates a new adapter with a linked asset', () => {
     const assetName1 = 'TestAsset1';
@@ -27,9 +28,13 @@ describe('Creates a new adapter with a linked asset', () => {
     beforeEach('Setup Test', () => {
         cy.initStreamPipesTest();
         AssetUtils.goToAssets();
-        AssetUtils.addAndSaveAsset(assetName3);
-        AssetUtils.addAndSaveAsset(assetName2);
-        AssetUtils.addAndSaveAsset(assetName1);
+
+        const asset1 = AssetBuilder.create(assetName1).build();
+        const asset2 = AssetBuilder.create(assetName2).build();
+        const asset3 = AssetBuilder.create(assetName3).build();
+        AssetUtils.addAndSaveAsset(asset3);
+        AssetUtils.addAndSaveAsset(asset2);
+        AssetUtils.addAndSaveAsset(asset1);
     });
 
     it('Add Assets during Chart generation', () => {
diff --git a/ui/cypress/tests/pipeline/pipelineAsset.spec.ts 
b/ui/cypress/tests/pipeline/pipelineAsset.spec.ts
index b42ecfe286..6a59cb3501 100644
--- a/ui/cypress/tests/pipeline/pipelineAsset.spec.ts
+++ b/ui/cypress/tests/pipeline/pipelineAsset.spec.ts
@@ -22,6 +22,7 @@ import { ConnectUtils } from 
'../../support/utils/connect/ConnectUtils';
 import { PipelineBuilder } from '../../support/builder/PipelineBuilder';
 import { PipelineElementBuilder } from 
'../../support/builder/PipelineElementBuilder';
 import { AssetBtns } from '../../support/utils/asset/AssetBtns';
+import { AssetBuilder } from '../../support/builder/AssetBuilder';
 
 describe('Test Saving Pipeline with Asset Link', () => {
     const assetName1 = 'Test1';
@@ -30,9 +31,12 @@ describe('Test Saving Pipeline with Asset Link', () => {
     beforeEach('Setup Test', () => {
         cy.initStreamPipesTest();
         AssetUtils.goToAssets();
-        AssetUtils.addAndSaveAsset(assetName3);
-        AssetUtils.addAndSaveAsset(assetName2);
-        AssetUtils.addAndSaveAsset(assetName1);
+        const asset1 = AssetBuilder.create(assetName1).build();
+        const asset2 = AssetBuilder.create(assetName2).build();
+        const asset3 = AssetBuilder.create(assetName3).build();
+        AssetUtils.addAndSaveAsset(asset3);
+        AssetUtils.addAndSaveAsset(asset2);
+        AssetUtils.addAndSaveAsset(asset1);
 
         // Generate A Pipeline
         const adapterName = 'simulator';
diff --git a/ui/cypress/tests/userManagement/testAddAssetOnResourceCreation.ts 
b/ui/cypress/tests/userManagement/testAddAssetOnResourceCreation.ts
index 97c963a015..008085ecf3 100644
--- a/ui/cypress/tests/userManagement/testAddAssetOnResourceCreation.ts
+++ b/ui/cypress/tests/userManagement/testAddAssetOnResourceCreation.ts
@@ -26,6 +26,7 @@ import { AdapterBuilder } from 
'../../support/builder/AdapterBuilder';
 import { DataExplorerUtils } from 
'../../support/utils/dataExplorer/DataExplorerUtils';
 import { DataExplorerBtns } from 
'../../support/utils/dataExplorer/DataExplorerBtns';
 import { ConnectBtns } from '../../support/utils/connect/ConnectBtns';
+import { AssetBuilder } from '../../support/builder/AssetBuilder';
 
 describe('Test that resources can be added to assets on creation', () => {
     let newUser;
@@ -41,7 +42,8 @@ describe('Test that resources can be added to assets on 
creation', () => {
         );
 
         AssetUtils.goToAssets();
-        AssetUtils.addAndSaveAsset('Asset');
+        const asset = AssetBuilder.create('Asset').build();
+        AssetUtils.addAndSaveAsset(asset);
     });
 
     it('Check Role Asset Admin in Connect', () => {
diff --git a/ui/cypress/tests/userManagement/testUserRoleAssets.spec.ts 
b/ui/cypress/tests/userManagement/testUserRoleAssets.spec.ts
index ede70029fc..f0d389592f 100644
--- a/ui/cypress/tests/userManagement/testUserRoleAssets.spec.ts
+++ b/ui/cypress/tests/userManagement/testUserRoleAssets.spec.ts
@@ -21,6 +21,7 @@ import { UserUtils } from '../../support/utils/UserUtils';
 import { User } from '../../support/model/User';
 import { AssetUtils } from '../../support/utils/asset/AssetUtils';
 import { PermissionUtils } from '../../support/utils/user/PermissionUtils';
+import { AssetBuilder } from '../../support/builder/AssetBuilder';
 
 describe('Test User Roles for Dashboards', () => {
     const assetName = 'test-asset';
@@ -112,7 +113,8 @@ describe('Test User Roles for Dashboards', () => {
     function setup() {
         UserUtils.switchUser(assetAdmin1);
         AssetUtils.goToAssets();
-        AssetUtils.addAndSaveAsset(assetName);
+        const asset = AssetBuilder.create(assetName).build();
+        AssetUtils.addAndSaveAsset(asset);
     }
 
     function assetIsVisibleAndEditableCanChangePermissions(user: User) {
diff --git 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-asset-model/asset-browser-filter-asset-model.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-asset-model/asset-browser-filter-asset-model.component.html
index e3e48e17cb..bbc517c4fa 100644
--- 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-asset-model/asset-browser-filter-asset-model.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-asset-model/asset-browser-filter-asset-model.component.html
@@ -32,10 +32,12 @@
             multiple
             [compareWith]="compare"
             [(ngModel)]="activeFilters.selectedAssetModels"
+            data-cy="filters-asset-select"
         >
             <mat-option
                 *ngFor="let asset of assets; let i = index"
                 [value]="asset"
+                [attr.data-cy]="'asset-option-' + asset.assetName"
                 class="smaller-font-size"
             >
                 {{ asset.assetName }}
diff --git 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-labels/asset-browser-filter-labels.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-labels/asset-browser-filter-labels.component.html
index d28b3b60e1..28b51b95be 100644
--- 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-labels/asset-browser-filter-labels.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-labels/asset-browser-filter-labels.component.html
@@ -32,10 +32,12 @@
             multiple
             [compareWith]="compare"
             [(ngModel)]="activeFilters.selectedLabels"
+            data-cy="filters-labels-select"
         >
             <mat-option
                 *ngFor="let label of labels; let i = index"
                 [value]="label"
+                [attr.data-cy]="'label-option-' + label.label"
             >
                 <sp-label
                     [labelText]="label.label"
diff --git 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-outer/asset-browser-filter-outer.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-outer/asset-browser-filter-outer.component.html
index f39d61b828..458d2f75f4 100644
--- 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-outer/asset-browser-filter-outer.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-outer/asset-browser-filter-outer.component.html
@@ -62,6 +62,7 @@
                     mat-button
                     mat-flat-button
                     class="small-button mat-basic btn-margin"
+                    [attr.data-cy]="'filters-deselect-' + title"
                     (click)="deselectAllEmitter.emit()"
                 >
                     {{ 'None' | translate }}
diff --git 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-sites/asset-browser-filter-sites.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-sites/asset-browser-filter-sites.component.html
index f126a2370d..9ab27ed6ed 100644
--- 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-sites/asset-browser-filter-sites.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-sites/asset-browser-filter-sites.component.html
@@ -32,10 +32,12 @@
             multiple
             [compareWith]="compare"
             [(ngModel)]="activeFilters.selectedSites"
+            data-cy="filters-sites-select"
         >
             <mat-option
                 *ngFor="let site of sites; let i = index"
                 [value]="site"
+                [attr.data-cy]="'site-option-' + site.label"
                 class="smaller-font-size"
             >
                 {{ site.label }}
diff --git 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-type/asset-browser-filter-type.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-type/asset-browser-filter-type.component.html
index b2d81fad89..aef8367c07 100644
--- 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-type/asset-browser-filter-type.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-type/asset-browser-filter-type.component.html
@@ -32,11 +32,13 @@
             multiple
             [compareWith]="compare"
             [(ngModel)]="activeFilters.selectedTypes"
+            data-cy="filters-types-select"
         >
             <mat-option
                 *ngFor="let assetType of allAssetTypes; let i = index"
                 [value]="assetType"
                 class="smaller-font-size"
+                [attr.data-cy]="'type-option-' + assetType.type"
             >
                 {{ assetType.label }}
             </mat-option>
diff --git 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter.component.html
index dcbaa8d4dd..9f88d64e4e 100644
--- 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter.component.html
@@ -41,10 +41,20 @@
         </sp-asset-browser-filter-labels>
         <mat-divider></mat-divider>
         <div fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="10px">
-            <button mat-flat-button class="mat-basic" (click)="resetFilters()">
+            <button
+                data-cy="reset-filters-btn"
+                mat-flat-button
+                class="mat-basic"
+                (click)="resetFilters()"
+            >
                 {{ 'Reset filters' | translate }}
             </button>
-            <button mat-flat-button color="accent" (click)="applyFilters()">
+            <button
+                data-cy="apply-filters-btn"
+                mat-flat-button
+                color="accent"
+                (click)="applyFilters()"
+            >
                 {{ 'Apply' | translate }}
             </button>
         </div>
diff --git 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-toolbar.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-toolbar.component.html
index d56c601f8f..e275d98b48 100644
--- 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-toolbar.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-browser/asset-browser-toolbar/asset-browser-toolbar.component.html
@@ -22,6 +22,7 @@
             mat-flat-button
             class="btn-secondary-outline btn-filter"
             color="secondary"
+            data-cy="filter-button"
             [matMenuTriggerFor]="menu"
             #menuTrigger="matMenuTrigger"
             [matTooltip]="'Filter assets' | translate"
diff --git 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-link-configuration/asset-link-configuration.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-link-configuration/asset-link-configuration.component.html
index 55a377e7b8..3bd81f6d4f 100644
--- 
a/ui/projects/streampipes/shared-ui/src/lib/components/asset-link-configuration/asset-link-configuration.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/asset-link-configuration/asset-link-configuration.component.html
@@ -33,6 +33,7 @@
                         <button
                             mat-icon-button
                             matTreeNodeToggle
+                            [attr.data-cy]="'toggle-' + node.assetName"
                             [attr.aria-label]="'Toggle ' + node.assetName"
                         >
                             <mat-icon>{{
diff --git 
a/ui/src/app/assets/components/asset-details/edit-asset/asset-details-panel/asset-details-basics/asset-details-basics.component.html
 
b/ui/src/app/assets/components/asset-details/edit-asset/asset-details-panel/asset-details-basics/asset-details-basics.component.html
index 009d20c3d4..6315e08ed2 100644
--- 
a/ui/src/app/assets/components/asset-details/edit-asset/asset-details-panel/asset-details-basics/asset-details-basics.component.html
+++ 
b/ui/src/app/assets/components/asset-details/edit-asset/asset-details-panel/asset-details-basics/asset-details-basics.component.html
@@ -34,6 +34,7 @@
                     subscriptSizing="dynamic"
                 >
                     <input
+                        data-cy="asset-name"
                         matInput
                         [(ngModel)]="asset.assetName"
                         [disabled]="!editMode"
@@ -84,6 +85,7 @@
             >
                 <mat-form-field class="w-100">
                     <mat-select
+                        data-cy="asset-type-select"
                         [disabled]="!editMode"
                         [(ngModel)]="asset.assetType.isa95AssetType"
                         aria-label="Asset Type"
@@ -91,6 +93,7 @@
                         <mat-option
                             *ngFor="let isaType of isa95Types"
                             [value]="isaType.type"
+                            [attr.data-cy]="'option-' + isaType.type"
                             >{{ isaType.label }}
                         </mat-option>
                     </mat-select>
diff --git 
a/ui/src/app/assets/components/asset-details/edit-asset/asset-details-panel/asset-details-basics/asset-details-labels/asset-details-labels.component.html
 
b/ui/src/app/assets/components/asset-details/edit-asset/asset-details-panel/asset-details-basics/asset-details-labels/asset-details-labels.component.html
index 7c2c8062d0..0566e1a7a4 100644
--- 
a/ui/src/app/assets/components/asset-details/edit-asset/asset-details-panel/asset-details-basics/asset-details-labels/asset-details-labels.component.html
+++ 
b/ui/src/app/assets/components/asset-details/edit-asset/asset-details-panel/asset-details-basics/asset-details-labels/asset-details-labels.component.html
@@ -50,6 +50,7 @@
                             ? 'No labels available - Click \'Manage Labels\''
                             : 'Click to add label'
                     "
+                    data-cy="asset-label-input"
                     #labelInput
                     [formControl]="labelCtrl"
                     [matChipInputFor]="chipGrid"
@@ -63,9 +64,11 @@
                     (optionSelected)="selected($event)"
                 >
                     @for (label of filteredLabels | async; track label) {
-                        <mat-option [value]="label._id">{{
-                            label.label
-                        }}</mat-option>
+                        <mat-option
+                            [value]="label._id"
+                            [attr.data-cy]="'option-' + label.label"
+                            >{{ label.label }}</mat-option
+                        >
                     }
                 </mat-autocomplete>
             </mat-form-field>
diff --git 
a/ui/src/app/assets/components/asset-details/edit-asset/asset-details-panel/asset-details-basics/asset-details-site/asset-details-site.component.html
 
b/ui/src/app/assets/components/asset-details/edit-asset/asset-details-panel/asset-details-basics/asset-details-site/asset-details-site.component.html
index 8a1dff7a21..5b3f328cc1 100644
--- 
a/ui/src/app/assets/components/asset-details/edit-asset/asset-details-panel/asset-details-basics/asset-details-site/asset-details-site.component.html
+++ 
b/ui/src/app/assets/components/asset-details/edit-asset/asset-details-panel/asset-details-basics/asset-details-site/asset-details-site.component.html
@@ -25,11 +25,16 @@
                 subscriptSizing="dynamic"
             >
                 <mat-select
+                    data-cy="asset-site-select"
                     [disabled]="!editMode"
                     [(ngModel)]="asset.assetSite.siteId"
                     (selectionChange)="handleLocationChange($event)"
                 >
-                    <mat-option *ngFor="let site of sites" [value]="site._id">
+                    <mat-option
+                        *ngFor="let site of sites"
+                        [attr.data-cy]="'option-' + site.label"
+                        [value]="site._id"
+                    >
                         {{ site.label }}
                     </mat-option>
                 </mat-select>
diff --git 
a/ui/src/app/assets/components/asset-details/edit-asset/asset-selection-panel/asset-selection-panel.component.html
 
b/ui/src/app/assets/components/asset-details/edit-asset/asset-selection-panel/asset-selection-panel.component.html
index 9c05862a7b..781b430c60 100644
--- 
a/ui/src/app/assets/components/asset-details/edit-asset/asset-selection-panel/asset-selection-panel.component.html
+++ 
b/ui/src/app/assets/components/asset-details/edit-asset/asset-selection-panel/asset-selection-panel.component.html
@@ -47,6 +47,9 @@
                                 "
                                 fxLayout="row"
                                 fxFlex="100"
+                                [attr.data-cy]="
+                                    'select-asset-' + node.assetName
+                                "
                                 (click)="selectNode(node, false)"
                             >
                                 <span fxLayoutAlign="end center" 
class="ml-5">{{
@@ -59,6 +62,9 @@
                                 >
                                     <button
                                         mat-icon-button
+                                        [attr.data-cy]="
+                                            'add-asset-' + node.assetName
+                                        "
                                         (click)="addAsset(node)"
                                         color="accent"
                                     >
@@ -115,6 +121,9 @@
                                         <button
                                             mat-icon-button
                                             (click)="addAsset(node)"
+                                            [attr.data-cy]="
+                                                'add-asset-' + node.assetName
+                                            "
                                             color="accent"
                                         >
                                             <i class="material-icons">add</i>

Reply via email to