Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Bind i18n models with namespace #2830

Merged
merged 11 commits into from
Feb 3, 2025
6 changes: 6 additions & 0 deletions .changeset/four-suits-run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@sap-ux-private/preview-middleware-client': patch
'@sap-ux/preview-middleware': patch
---

Bind i18n models with namespace
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export async function applyChange(options: UI5AdaptationOptions, change: Propert
const changeType = isBindingString ? 'BindProperty' : 'Property';

if (isBindingModel) {
validateBindingModel(modifiedControl, change.value as string);
await validateBindingModel(modifiedControl, change.value as string);
}

const property = isBindingString ? 'newBinding' : 'newValue';
Expand Down
30 changes: 16 additions & 14 deletions packages/preview-middleware-client/src/cpe/changes/validator.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
import ResourceBundle from 'sap/base/i18n/ResourceBundle';
import ResourceModel from 'sap/ui/model/resource/ResourceModel';
import type UI5Element from 'sap/ui/core/Element';
import { getTextBundle } from '../../i18n';

/**
* Function to validate if a given value is a valid binding model.
*
* @param modifiedControl control to be modified.
* @param value value to be checked.
*/
export function validateBindingModel(modifiedControl: UI5Element, value: string): void {
export async function validateBindingModel(modifiedControl: UI5Element, value: string): Promise<void> {
const textBundle = await getTextBundle();
const bindingValue = value.replace(/[{}]/gi, '').trim();
const bindingParts = bindingValue.split('>').filter((el) => el !== '');

if (!bindingParts.length) {
throw new SyntaxError('Invalid binding string.');
throw new SyntaxError(textBundle.getText('INVALID_BINDING_STRING'));
}

if (bindingParts[0].trim() === 'i18n') {
if (bindingParts.length === 2) {
const resourceKey = bindingParts[1].trim();
const resourceBundle = (modifiedControl.getModel('i18n') as ResourceModel).getResourceBundle() as ResourceBundle;
if (!resourceBundle.getText(resourceKey, undefined, true)) {
throw new SyntaxError(
'Invalid key in the binding string. Supported value pattern is {i18n>YOUR_KEY}. Check if the key already exists in i18n.properties.' +
'If not, add the key in the i18n.properties file and reload the editor for the new key to take effect.'
);
}
} else {
throw new SyntaxError('Invalid binding string. Supported value pattern is {i18n>YOUR_KEY}');
if (bindingParts.length === 2) {
const bindingModel = bindingParts[0];
const resourceKey = bindingParts[1].trim();
const resourceModel = (modifiedControl.getModel(bindingModel) as ResourceModel);
if(!resourceModel) {
throw new SyntaxError(textBundle.getText('INVALID_BINDING_MODEL'));
}
const resourceBundle = resourceModel.getResourceBundle() as ResourceBundle;
if (!resourceBundle.getText(resourceKey, undefined, true)) {
throw new SyntaxError(textBundle.getText('INVALID_BINDING_MODEL_KEY'));
}
} else {
throw new SyntaxError(textBundle.getText('INVALID_BINDING_STRING_FORMAT'));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,8 @@ EXTEND_WITH_ANNOTATION=Extend With Annotation
ANNOTATION_FILE_HAS_BEEN_FOUND=An annotation file has been found.
SHOW_FILE_IN_VSCODE=Show File in VSCode

INVALID_BINDING_STRING=Invalid binding string.
INVALID_BINDING_STRING_FORMAT=Invalid binding string. Supported value pattern is {i18n>YOUR_KEY}
INVALID_BINDING_MODEL=Invalid binding model.
INVALID_BINDING_MODEL_KEY=Invalid key in the binding string. Supported value pattern is {i18n>YOUR_KEY}. Check if the key already exists in i18n.properties.If not, add the key in the i18n.properties file and reload the editor for the new key to take effect.

Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,23 @@ describe('vaildateBindingModel', () => {
)
})
};
test('should throw when invalid binding model string is provided', () => {
try {
validateBindingModel(mockModifiedcontrol as unknown as UI5Element, '{}');
} catch (error) {
expect(error).toBeInstanceOf(SyntaxError);
expect(error.message).toBe('Invalid binding string.');
}

test('should throw when invalid binding model string is provided', async () => {
await expect(() => validateBindingModel(mockModifiedcontrol as unknown as UI5Element, '{}')).rejects.toThrow('Invalid binding string.');
});

test('should throw when invalid binding string for i18n model is provided', async () => {
await expect(() => validateBindingModel(mockModifiedcontrol as unknown as UI5Element, '{ i18n }')).rejects.toThrow('Invalid binding string. Supported value pattern is {i18n>YOUR_KEY}');
});

test('should throw when invalid binding string for i18n model is provided', () => {
try {
validateBindingModel(mockModifiedcontrol as unknown as UI5Element, '{ i18n }');
} catch (error) {
expect(error).toBeInstanceOf(SyntaxError);
expect(error.message).toBe('Invalid binding string. Supported value pattern is {i18n>YOUR_KEY}');
}
test('should throw when the provided key does not exist in i18n.properties', async () => {
await expect(() => validateBindingModel(mockModifiedcontrol as unknown as UI5Element, '{ i18n>test }')).rejects.toThrow('Invalid key in the binding string. Supported value pattern is {i18n>YOUR_KEY}. Check if the key already exists in i18n.properties.If not, add the key in the i18n.properties file and reload the editor for the new key to take effect.');
});

test('should throw when the provided key does not exist in i18n.properties', () => {
try {
validateBindingModel(mockModifiedcontrol as unknown as UI5Element, '{ i18n>test }');
} catch (error) {
expect(error).toBeInstanceOf(SyntaxError);
expect(error.message).toBe(
'Invalid key in the binding string. Supported value pattern is {i18n>YOUR_KEY}. Check if the key already exists in i18n.properties.If not, add the key in the i18n.properties file and reload the editor for the new key to take effect.'
);
}
test('should throw error when invalid binding model is provided', async () => {
const control = {
getModel: jest.fn().mockReturnValue(undefined)
};
await expect(() => validateBindingModel(control as unknown as UI5Element, '{ i18n>test }')).rejects.toThrow('Invalid binding model.');
});
});
Loading