@sap-ux/ui5-test-writer 1.2.18 → 1.2.19

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.
package/dist/types.d.ts CHANGED
@@ -108,6 +108,8 @@ export type ObjectPageNavigationParents = {
108
108
  };
109
109
  export type SectionFormField = {
110
110
  property: string;
111
+ connectedFields?: string;
112
+ fieldGroup?: string;
111
113
  };
112
114
  export type TableColumn = {
113
115
  header?: string;
@@ -107,4 +107,14 @@ export declare function getSelectionFieldItems(selectionFieldsAgg: TreeAggregati
107
107
  * @returns An array of filter field descriptions.
108
108
  */
109
109
  export declare function getFilterFields(pageModel: TreeModel): TreeAggregations;
110
+ /**
111
+ * Parses a `DataFieldForAnnotation::<property>::<targetAnnotation>` style identifier.
112
+ *
113
+ * @param name - aggregation key or `field.name` from the spec model
114
+ * @returns the parsed property and target annotation, or undefined for non-annotation entries
115
+ */
116
+ export declare function parseDataFieldForAnnotationName(name: string | undefined): {
117
+ property: string;
118
+ targetAnnotation: string;
119
+ } | undefined;
110
120
  //# sourceMappingURL=modelUtils.d.ts.map
@@ -174,4 +174,25 @@ export function getFilterFields(pageModel) {
174
174
  const selectionFieldsAggregations = getAggregations(selectionFields);
175
175
  return selectionFieldsAggregations;
176
176
  }
177
+ /**
178
+ * Parses a `DataFieldForAnnotation::<property>::<targetAnnotation>` style identifier.
179
+ *
180
+ * @param name - aggregation key or `field.name` from the spec model
181
+ * @returns the parsed property and target annotation, or undefined for non-annotation entries
182
+ */
183
+ export function parseDataFieldForAnnotationName(name) {
184
+ if (!name) {
185
+ return undefined;
186
+ }
187
+ const segments = name.split('::');
188
+ if (segments.length < 3 || segments[0] !== 'DataFieldForAnnotation') {
189
+ return undefined;
190
+ }
191
+ const property = segments[1];
192
+ const targetAnnotation = segments[2];
193
+ if (!property || !targetAnnotation) {
194
+ return undefined;
195
+ }
196
+ return { property, targetAnnotation };
197
+ }
177
198
  //# sourceMappingURL=modelUtils.js.map
@@ -1,4 +1,4 @@
1
- import { getAggregations } from './modelUtils.js';
1
+ import { getAggregations, parseDataFieldForAnnotationName } from './modelUtils.js';
2
2
  import { extractTableColumnsFromNode } from './tableUtils.js';
3
3
  import { PageTypeV4 } from '@sap/ux-specification/dist/types/src/common/page.js';
4
4
  import { parse } from '@sap-ux/edmx-parser';
@@ -133,7 +133,7 @@ function extractObjectPageBodySectionsData(objectPage, convertedMetadata, schema
133
133
  const sections = getAggregations(sectionsAggregation);
134
134
  Object.entries(sections).forEach(([sectionKey, section]) => {
135
135
  const sectionId = getSectionIdentifier(section) ?? sectionKey;
136
- const subSections = extractBodySubSectionsData(section, sectionId);
136
+ const subSections = extractBodySubSectionsData(section, sectionId, convertedMetadata, objectPage.entitySet);
137
137
  const navigationProperty = getNavigationPropertyFromKey(sectionKey);
138
138
  const isTable = isTableSection(section);
139
139
  const sectionData = {
@@ -142,7 +142,9 @@ function extractObjectPageBodySectionsData(objectPage, convertedMetadata, schema
142
142
  isTable,
143
143
  custom: !!section.custom,
144
144
  order: section?.order ?? -1,
145
- fields: section.custom || isTable ? [] : extractFormFields(section),
145
+ fields: section.custom || isTable
146
+ ? []
147
+ : extractFormFields(section, convertedMetadata, objectPage.entitySet),
146
148
  tableColumns: section.custom || !isTable ? {} : extractTableColumnsFromNode(section),
147
149
  subSections,
148
150
  actions: !section.custom && convertedMetadata && schemaNamespace
@@ -215,9 +217,11 @@ function extractSectionActions(section, convertedMetadata, schemaNamespace) {
215
217
  *
216
218
  * @param section - body section entry from the application model
217
219
  * @param parentSectionId - identifier of the parent section (used as fallback key prefix)
220
+ * @param convertedMetadata - optional converted OData metadata for drilling into ConnectedFields / FieldGroup wrappers
221
+ * @param entitySetName - the entity set the section is bound to (used to locate the entity type)
218
222
  * @returns array of sub-section feature data
219
223
  */
220
- function extractBodySubSectionsData(section, parentSectionId) {
224
+ function extractBodySubSectionsData(section, parentSectionId, convertedMetadata, entitySetName) {
221
225
  const subSections = [];
222
226
  const subSectionsAggregation = getAggregations(section)['subSections'];
223
227
  const subSectionItems = getAggregations(subSectionsAggregation);
@@ -230,7 +234,7 @@ function extractBodySubSectionsData(section, parentSectionId) {
230
234
  isTable,
231
235
  custom: !!subSection.custom,
232
236
  order: subSection?.order ?? -1, // put a negative order number to signal that order was not in spec
233
- fields: subSection.custom || isTable ? [] : extractFormFields(subSection),
237
+ fields: subSection.custom || isTable ? [] : extractFormFields(subSection, convertedMetadata, entitySetName),
234
238
  tableColumns: subSection.custom || !isTable ? {} : extractTableColumnsFromNode(subSection)
235
239
  });
236
240
  });
@@ -240,9 +244,11 @@ function extractBodySubSectionsData(section, parentSectionId) {
240
244
  * Extracts form field property paths from a body sub-section's form aggregation.
241
245
  *
242
246
  * @param subSection - body sub-section entry from the application model
247
+ * @param convertedMetadata - optional converted OData metadata for drilling into ConnectedFields / FieldGroup wrappers
248
+ * @param entitySetName - the entity set the sub-section is bound to (used to locate the entity type)
243
249
  * @returns array of form field property paths for use with iCheckField({ property })
244
250
  */
245
- function extractFormFields(subSection) {
251
+ function extractFormFields(subSection, convertedMetadata, entitySetName) {
246
252
  const fields = [];
247
253
  const formAggregation = getAggregations(subSection)['form'];
248
254
  if (!formAggregation) {
@@ -250,14 +256,71 @@ function extractFormFields(subSection) {
250
256
  }
251
257
  const fieldsAggregation = getAggregations(formAggregation)['fields'];
252
258
  const fieldItems = getAggregations(fieldsAggregation);
253
- Object.values(fieldItems).forEach((field) => {
254
- const property = field.schema?.keys?.find((key) => key.name === 'Value')?.value;
255
- if (property) {
256
- fields.push({ property });
259
+ const entityType = convertedMetadata && entitySetName ? resolveEntityType(convertedMetadata, entitySetName) : undefined;
260
+ Object.values(fieldItems).forEach((fieldItem) => {
261
+ const annotationParts = parseDataFieldForAnnotationName(fieldItem.name);
262
+ const valueProperty = fieldItem.schema?.keys?.find((key) => key.name === 'Value')?.value;
263
+ const baseProperty = valueProperty ?? annotationParts?.property;
264
+ if (!baseProperty) {
265
+ return;
266
+ }
267
+ if (annotationParts) {
268
+ const qualifier = annotationParts.targetAnnotation;
269
+ if (annotationParts.property === 'ConnectedFields' && entityType) {
270
+ resolveConnectedFieldsInnerProperties(entityType, qualifier).forEach((property) => {
271
+ fields.push({ property, connectedFields: qualifier });
272
+ });
273
+ }
274
+ else if (annotationParts.property === 'FieldGroup' && entityType) {
275
+ resolveFieldGroupInnerProperties(entityType, qualifier).forEach((property) => {
276
+ fields.push({ property, fieldGroup: qualifier });
277
+ });
278
+ }
279
+ // ConnectedFields/FieldGroup without metadata: skip
280
+ // Unknown annotation wrapper type: skip
281
+ }
282
+ else {
283
+ fields.push({ property: baseProperty });
257
284
  }
258
285
  });
259
286
  return fields;
260
287
  }
288
+ /**
289
+ * Resolves the inner `Value` paths of a `@UI.ConnectedFields#<qualifier>` annotation.
290
+ *
291
+ * @param entityType - the entity type carrying the annotation
292
+ * @param qualifier - the annotation qualifier
293
+ * @returns the inner DataField property paths
294
+ */
295
+ function resolveConnectedFieldsInnerProperties(entityType, qualifier) {
296
+ const annotation = entityType.annotations?.UI?.[`ConnectedFields#${qualifier}`];
297
+ const dictionary = annotation?.Data ?? {};
298
+ return Object.values(dictionary)
299
+ .map((dataField) => dataField?.Value?.path)
300
+ .filter((path) => Boolean(path));
301
+ }
302
+ /**
303
+ * Resolves the inner `Value` paths of a `@UI.FieldGroup#<qualifier>` annotation.
304
+ *
305
+ * @param entityType - the entity type carrying the annotation
306
+ * @param qualifier - the annotation qualifier
307
+ * @returns the inner DataField property paths
308
+ */
309
+ function resolveFieldGroupInnerProperties(entityType, qualifier) {
310
+ const annotation = entityType.annotations?.UI?.[`FieldGroup#${qualifier}`];
311
+ const dataFields = annotation?.Data ?? [];
312
+ return dataFields.map((dataField) => dataField?.Value?.path).filter((path) => Boolean(path));
313
+ }
314
+ /**
315
+ * Looks up the entity type for the given entity set name in the converted metadata.
316
+ *
317
+ * @param convertedMetadata - the converted OData metadata
318
+ * @param entitySetName - the entity set name
319
+ * @returns the entity type, or undefined if not found
320
+ */
321
+ function resolveEntityType(convertedMetadata, entitySetName) {
322
+ return convertedMetadata.entitySets.find((es) => es.name === entitySetName)?.entityType;
323
+ }
261
324
  /**
262
325
  * Extracts the OData navigation property from a spec model section key.
263
326
  * Section keys for table sections follow the pattern `_NavProperty::@annotation`, so the
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sap-ux/ui5-test-writer",
3
3
  "description": "SAP UI5 tests writer",
4
- "version": "1.2.18",
4
+ "version": "1.2.19",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/SAP/open-ux-tools.git",
@@ -129,7 +129,7 @@ sap.ui.define([
129
129
  Then.onThe<%- name%>Generated.iCheckSubSection({ section: "<%- subSection.id %>" });
130
130
  <% if (subSection.fields && subSection.fields.length > 0) { -%>
131
131
  <% subSection.fields.forEach(function(field) { -%>
132
- Then.onThe<%- name%>Generated.onForm({ section: "<%- subSection.id %>" }).iCheckField({ property: "<%- field.property %>" });
132
+ Then.onThe<%- name%>Generated.onForm({ section: "<%- subSection.id %>" }).iCheckField({ property: "<%- field.property %>"<% if (field.connectedFields) { %>, connectedFields: "<%- field.connectedFields %>"<% } %><% if (field.fieldGroup) { %>, fieldGroup: "<%- field.fieldGroup %>"<% } %> });
133
133
  <% }) -%>
134
134
  <% } -%>
135
135
  <% if (subSection.tableColumns && Object.keys(subSection.tableColumns).length > 0 && subSection.navigationProperty) { -%>
@@ -139,7 +139,7 @@ sap.ui.define([
139
139
  <% } else { -%>
140
140
  <% if (section.fields && section.fields.length > 0) { -%>
141
141
  <% section.fields.forEach(function(field) { -%>
142
- Then.onThe<%- name%>Generated.onForm({ section: "<%- section.id %>" }).iCheckField({ property: "<%- field.property %>" });
142
+ Then.onThe<%- name%>Generated.onForm({ section: "<%- section.id %>" }).iCheckField({ property: "<%- field.property %>"<% if (field.connectedFields) { %>, connectedFields: "<%- field.connectedFields %>"<% } %><% if (field.fieldGroup) { %>, fieldGroup: "<%- field.fieldGroup %>"<% } %> });
143
143
  <% }) -%>
144
144
  <% } -%>
145
145
  <% if (section.tableColumns && Object.keys(section.tableColumns).length > 0 && section.navigationProperty) { -%>
@@ -148,7 +148,7 @@ function journey() {
148
148
  Then.onThe<%- name%>Generated.iCheckSubSection({ section: "<%- subSection.id %>" });
149
149
  <% if (subSection.fields && subSection.fields.length > 0) { -%>
150
150
  <% subSection.fields.forEach(function(field) { -%>
151
- Then.onThe<%- name%>Generated.onForm({ section: "<%- subSection.id %>" } as unknown as FormIdentifier).iCheckField({ property: "<%- field.property %>" });
151
+ Then.onThe<%- name%>Generated.onForm({ section: "<%- subSection.id %>" } as unknown as FormIdentifier).iCheckField({ property: "<%- field.property %>"<% if (field.connectedFields) { %>, connectedFields: "<%- field.connectedFields %>"<% } %><% if (field.fieldGroup) { %>, fieldGroup: "<%- field.fieldGroup %>"<% } %> });
152
152
  <% }) -%>
153
153
  <% } -%>
154
154
  <% if (subSection.tableColumns && Object.keys(subSection.tableColumns).length > 0 && subSection.navigationProperty) { -%>
@@ -158,7 +158,7 @@ function journey() {
158
158
  <% } else { -%>
159
159
  <% if (section.fields && section.fields.length > 0) { -%>
160
160
  <% section.fields.forEach(function(field) { -%>
161
- Then.onThe<%- name%>Generated.onForm({ section: "<%- section.id %>" } as unknown as FormIdentifier).iCheckField({ property: "<%- field.property %>" });
161
+ Then.onThe<%- name%>Generated.onForm({ section: "<%- section.id %>" } as unknown as FormIdentifier).iCheckField({ property: "<%- field.property %>"<% if (field.connectedFields) { %>, connectedFields: "<%- field.connectedFields %>"<% } %><% if (field.fieldGroup) { %>, fieldGroup: "<%- field.fieldGroup %>"<% } %> });
162
162
  <% }) -%>
163
163
  <% } -%>
164
164
  <% if (section.tableColumns && Object.keys(section.tableColumns).length > 0 && section.navigationProperty) { -%>