@sapui5/sap.fe.test 1.130.6 → 1.132.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,7 @@ import merge from "sap/base/util/merge";
10
10
  import uid from "sap/base/util/uid";
11
11
  import jsx from "sap/fe/base/jsx-runtime/jsx";
12
12
  import AppComponent from "sap/fe/core/AppComponent";
13
+ import PageController from "sap/fe/core/PageController";
13
14
  import type TemplateComponent from "sap/fe/core/TemplateComponent";
14
15
  import TemplateModel from "sap/fe/core/TemplateModel";
15
16
  import { parseXMLString } from "sap/fe/core/buildingBlocks/templating/BuildingBlockTemplateProcessor";
@@ -101,7 +102,8 @@ const nameSpaceMap: Record<string, string> = {
101
102
  valueHelp: "sap.fe.macros.valueHelp",
102
103
  contentSwitcher: "sap.fe.macros.contentSwitcher",
103
104
  filterBar: "sap.fe.macros.filterBar",
104
- fbControls: "sap.fe.macros.controls.filterbar"
105
+ fbControls: "sap.fe.macros.controls.filterbar",
106
+ draftIndicator: "sap.fe.macros.draftIndicator"
105
107
  };
106
108
  const reveseNamespaceMap = Object.keys(nameSpaceMap).reduce((reverseMap: Record<string, string>, currentName) => {
107
109
  reverseMap[nameSpaceMap[currentName]] = currentName;
@@ -840,6 +842,188 @@ export function serializeControl(controlToSerialize?: UI5Element | UI5Element[],
840
842
  }
841
843
  }
842
844
 
845
+ export function serializeControlAsXML(controlToSerialize?: UI5Element | UI5Element[], showCustomStyleClasses = false) {
846
+ let tabCount = 0;
847
+ const UID = /uid--id-\d{13}-\d{1,3}/;
848
+ const CONTROLID = /id-\d{13}-\d{1,3}/;
849
+ const definedNamespaces: Record<string, boolean> = {};
850
+
851
+ function getNamespaceAlias(className: string): string {
852
+ const namesSplit = className.split(".");
853
+ const namespace = namesSplit.slice(0, -1);
854
+ const name = namesSplit[namesSplit.length - 1];
855
+ let namespaceAlias = namespace[namespace.length - 1];
856
+ if (reveseNamespaceMap[namespace.join(".")]) {
857
+ namespaceAlias = reveseNamespaceMap[namespace.join(".")];
858
+ }
859
+ if (namespaceAlias === undefined) {
860
+ namespaceAlias = "test";
861
+ }
862
+ return namespaceAlias;
863
+ }
864
+
865
+ function getTab(toAdd = 0) {
866
+ let tab = "";
867
+ for (let i = 0; i < tabCount + toAdd; i++) {
868
+ tab += "\t";
869
+ }
870
+ return tab;
871
+ }
872
+ const serializeDelegate = {
873
+ start: function (control: any, sAggregationName: string) {
874
+ let controlDetail = "";
875
+ if (sAggregationName) {
876
+ if (control.getParent()) {
877
+ const indexInParent = (control.getParent().getAggregation(sAggregationName) as ManagedObject[])?.indexOf?.(control);
878
+ if (indexInParent > 0) {
879
+ controlDetail += `\n${getTab()}`;
880
+ }
881
+ }
882
+ }
883
+ const nameFull = control.getMetadata().getName();
884
+ const namesSplit = nameFull.split(".");
885
+ const name = namesSplit[namesSplit.length - 1];
886
+ const namespaceAlias = getNamespaceAlias(nameFull);
887
+ controlDetail += `<${namespaceAlias}:${name}\n`;
888
+ if (!definedNamespaces[namespaceAlias]) {
889
+ definedNamespaces[namespaceAlias] = true;
890
+ controlDetail += `${getTab()}xmlns:${namespaceAlias}="${nameSpaceMap[namespaceAlias]}"`;
891
+ }
892
+ return controlDetail;
893
+ },
894
+ end: function (control: any) {
895
+ const nameFull = control.getMetadata().getName();
896
+ const namesSplit = nameFull.split(".");
897
+ const name = namesSplit[namesSplit.length - 1];
898
+ const namespaceAlias = getNamespaceAlias(nameFull);
899
+ let hasAggregation = false;
900
+ for (const mAggregationsKey in control.mAggregations) {
901
+ if (
902
+ (!Array.isArray(control.mAggregations[mAggregationsKey]) &&
903
+ control.mAggregations[mAggregationsKey] !== null &&
904
+ control.mAggregations[mAggregationsKey] !== undefined) ||
905
+ (Array.isArray(control.mAggregations[mAggregationsKey]) && control.mAggregations[mAggregationsKey].length > 0)
906
+ ) {
907
+ hasAggregation = true;
908
+ }
909
+ }
910
+ if (hasAggregation) {
911
+ return `</${namespaceAlias}:${name}>`;
912
+ } else {
913
+ return `/>`;
914
+ }
915
+ },
916
+ middle: function (control: any) {
917
+ let id = control.getId();
918
+ id = typeof id === "string" ? id?.replace?.(CONTROLID, "id") : id;
919
+ let data = "";
920
+ if (!ManagedObjectMetadata.isGeneratedId(id)) {
921
+ data = `id="${id}"`;
922
+ }
923
+ let keys = Object.keys(control.mProperties)
924
+ .concat(Object.keys(control.mBindingInfos))
925
+ .concat(Object.keys(control.mAssociations))
926
+ .concat(Object.keys(control.mEventRegistry));
927
+ keys = keys.sort((a, b) => a.localeCompare(b));
928
+ const uniqueKeys = new Set(keys);
929
+ keys = Array.from(uniqueKeys);
930
+ for (const oControlKey of keys) {
931
+ if (control.mBindingInfos.hasOwnProperty(oControlKey)) {
932
+ const bindingDetail = { ...control.mBindingInfos[oControlKey] };
933
+ if (bindingDetail.bindingString) {
934
+ data += `\n${getTab()}${oControlKey}="${bindingDetail.bindingString.replace(">", "&gt;")}"`;
935
+ } else {
936
+ if (bindingDetail.type?.oOutputFormat) {
937
+ delete bindingDetail.type.oOutputFormat;
938
+ }
939
+
940
+ if (bindingDetail.binding) {
941
+ delete bindingDetail.binding;
942
+ }
943
+ if (bindingDetail.template) {
944
+ delete bindingDetail.template;
945
+ }
946
+ data += `\n${getTab()}${oControlKey}='${JSON.stringify(bindingDetail)}'`;
947
+ }
948
+ } else if (control.mProperties.hasOwnProperty(oControlKey) && control.mProperties[oControlKey] !== undefined) {
949
+ let propertyValue = control.mProperties[oControlKey];
950
+ propertyValue = typeof propertyValue === "string" ? propertyValue?.replace?.(UID, "uid--id") : propertyValue;
951
+ propertyValue = typeof propertyValue === "string" ? propertyValue?.replace?.(CONTROLID, "id") : propertyValue;
952
+ try {
953
+ propertyValue = typeof propertyValue === "object" ? JSON.stringify(propertyValue) : propertyValue;
954
+ } catch (e) {
955
+ // Stringify may fail for circular references but it's not the end of the world
956
+ }
957
+
958
+ data += `\n${getTab()} ${oControlKey}="${propertyValue}"`;
959
+ } else if (control.mAssociations.hasOwnProperty(oControlKey)) {
960
+ let associationValue = control.mAssociations[oControlKey];
961
+ if (!Array.isArray(associationValue)) {
962
+ associationValue = [associationValue];
963
+ }
964
+ associationValue = associationValue.map((associationValueElement: string) => {
965
+ return typeof associationValueElement === "string"
966
+ ? associationValueElement?.replace?.(CONTROLID, "id")
967
+ : associationValueElement;
968
+ });
969
+
970
+ data += `\n${getTab()} ${oControlKey}="${(associationValue?.join?.(",") ?? associationValue) || undefined}"`;
971
+ } else if (control.mEventRegistry.hasOwnProperty(oControlKey)) {
972
+ if (control.mEventRegistry[oControlKey][0]?.fFunction?.name) {
973
+ data += `\n${getTab()} ${oControlKey}="${control.mEventRegistry[oControlKey][0]?.fFunction?.name}"`;
974
+ } else {
975
+ data += `\n${getTab()} ${oControlKey}="someEventHandler"`;
976
+ }
977
+ }
978
+ }
979
+ if (showCustomStyleClasses && control.aCustomStyleClasses?.length > 0) {
980
+ data += `\n${getTab()} customStyleClasses : ${control.aCustomStyleClasses.join(", ")}`;
981
+ }
982
+ data += `\n`;
983
+ let hasAggregation = false;
984
+ for (const mAggregationsKey in control.mAggregations) {
985
+ if (
986
+ (!Array.isArray(control.mAggregations[mAggregationsKey]) &&
987
+ control.mAggregations[mAggregationsKey] !== null &&
988
+ control.mAggregations[mAggregationsKey] !== undefined) ||
989
+ (Array.isArray(control.mAggregations[mAggregationsKey]) && control.mAggregations[mAggregationsKey].length > 0)
990
+ ) {
991
+ hasAggregation = true;
992
+ }
993
+ }
994
+ if (hasAggregation) {
995
+ data += ">";
996
+ }
997
+ return data;
998
+ },
999
+ startAggregation: function (control: any, sName: string) {
1000
+ const namespaceAlias = getNamespaceAlias(control.getMetadata().getName());
1001
+ let out = `\n${getTab()}<${namespaceAlias}:${sName}>`;
1002
+ tabCount++;
1003
+ out += `\n${getTab()}`;
1004
+ return out;
1005
+ },
1006
+ endAggregation: function (control: any, sName: string) {
1007
+ tabCount--;
1008
+ const namespaceAlias = getNamespaceAlias(control.getMetadata().getName());
1009
+ if (control.mBindingInfos[sName]) {
1010
+ return `\n${getTab()}</${namespaceAlias}:${sName}>\n`;
1011
+ } else {
1012
+ return `\n${getTab()}</${namespaceAlias}:${sName}>\n`;
1013
+ }
1014
+ }
1015
+ };
1016
+ let outXML;
1017
+ if (Array.isArray(controlToSerialize)) {
1018
+ outXML = controlToSerialize.map((controlToRender: UI5Element) => {
1019
+ return new Serializer(controlToRender, serializeDelegate).serialize();
1020
+ });
1021
+ } else {
1022
+ outXML = new Serializer(controlToSerialize, serializeDelegate).serialize();
1023
+ }
1024
+ return formatXML(`<root>${outXML}</root>`);
1025
+ }
1026
+
843
1027
  export function createAwaiter() {
844
1028
  let fnResolve!: Function;
845
1029
  const myPromise = new Promise((resolve) => {
@@ -911,7 +1095,11 @@ export async function initializeAppComponent(
911
1095
  const id = options?.componentId ?? `sap.fe.test.${guid}`;
912
1096
  const cdsContent = fs.readFileSync(cdsFile).toString();
913
1097
  sap.jest.registerFakeFragment(`/sap/fe/core/mock/${guid}/$metadata?sap-language=EN`, cdsContent);
914
-
1098
+ class DefaultPageContent extends PageController {
1099
+ render() {
1100
+ return <Page></Page>;
1101
+ }
1102
+ }
915
1103
  sap.ui.define(`sap/fe/test/${guid}/Component`, ["sap/fe/core/AppComponent"], function (_AppComponent: AppComponent) {
916
1104
  "use strict";
917
1105
 
@@ -919,6 +1107,7 @@ export async function initializeAppComponent(
919
1107
  metadata: {
920
1108
  manifest: {
921
1109
  "sap.app": {
1110
+ id: `test${guid}`,
922
1111
  dataSources: {
923
1112
  mainService: {
924
1113
  uri: `/sap/fe/core/mock/${guid}/`,
@@ -948,7 +1137,7 @@ export async function initializeAppComponent(
948
1137
  ...(options?.manifestSettings ?? {}),
949
1138
  contextPath: options?.mainContextPath ?? "/Products",
950
1139
  viewType: "JSX",
951
- viewContent: options?.pageContent ?? (() => <Page></Page>),
1140
+ viewContent: options?.pageContent ?? DefaultPageContent,
952
1141
  content: options?.content
953
1142
  }
954
1143
  }
@@ -1003,3 +1192,11 @@ export async function waitForEvent(control: EventProvider, eventName: string): P
1003
1192
  });
1004
1193
  });
1005
1194
  }
1195
+
1196
+ /**
1197
+ * Tell the binding parser to keep the binding strings for testing.
1198
+ * @param enabled
1199
+ */
1200
+ export function keepBindingStringForTest(enabled: boolean): void {
1201
+ BindingParser._keepBindingStrings = enabled;
1202
+ }
@@ -293,6 +293,9 @@ sap.ui.define(
293
293
  .clickKPITag(sTitle)
294
294
  .description("Opening card for KPI '" + sTitle + "'")
295
295
  .execute();
296
+ },
297
+ iCloseKPICard: function () {
298
+ return KPIBuilder.create(this).closeKPICard().description("Closing KPI card").execute();
296
299
  }
297
300
  },
298
301
  /**
@@ -464,7 +467,7 @@ sap.ui.define(
464
467
  return OpaBuilder.create(this)
465
468
  .hasType("sap.f.DynamicPageTitle")
466
469
  .has(function (oDynamicPageTitle) {
467
- return oDynamicPageTitle.getSnappedContent()[0].getText() === sAppliedFilters;
470
+ return oDynamicPageTitle.getSnappedContent()[0].getContent().getText() === sAppliedFilters;
468
471
  })
469
472
  .description("The correct text on the collapsed filterbar is displayed")
470
473
  .execute();
@@ -585,8 +585,8 @@ sap.ui.define(
585
585
  return OpaBuilder.create(this)
586
586
  .hasType("sap.m.MessageListItem")
587
587
  .hasProperties({
588
- title: oMessageInfo.MessageText,
589
- groupAnnouncement: oMessageInfo.GroupLabel
588
+ title: oMessageInfo.MessageText
589
+ //groupAnnouncement: oMessageInfo.GroupLabel => with openui5/+/6328248 groups are no longer announced
590
590
  })
591
591
  .isDialogElement(true)
592
592
  .description("MessageItem with correct text and group label")
@@ -746,7 +746,7 @@ sap.ui.define(
746
746
  },
747
747
  iSeeBetterLinkWithText: function (sText) {
748
748
  return OpaBuilder.create(this)
749
- .hasType("sap.fe.macros.controls.BetterLink")
749
+ .hasType("sap.fe.macros.controls.TextLink")
750
750
  .hasProperties({ text: sText })
751
751
  .description("Seeing Text with text '" + sText + "'")
752
752
  .execute();