lodash#partial TypeScript Examples
The following examples show how to use
lodash#partial.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: packet.utils.ts From nestjs-jaeger-tracing with MIT License | 6 votes |
export function isRequestPacket<T>(
packet: unknown,
): packet is RequestPacket<T> {
const keys: Array<keyof RequestPacket<T>> = ['id', 'data', 'pattern'];
return every(keys, partial(has, packet));
}
Example #2
Source File: packet.utils.ts From nestjs-jaeger-tracing with MIT License | 6 votes |
export function isTracingContext(packet: unknown): packet is TracingContext {
const keys: Array<keyof TracingContext> = ['payload', 'isSerialized'];
return every(keys, partial(has, packet));
}
Example #3
Source File: convert.ts From ui5-language-assistant with Apache License 2.0 | 6 votes |
function convertNamespace(
libName: string,
symbol: apiJson.NamespaceSymbol | apiJson.DatatypeSymbol
): model.UI5Namespace {
const base = convertSymbol(libName, symbol);
const namespace: model.UI5Namespace = {
...base,
kind: "UI5Namespace",
fields: [],
methods: [],
events: [],
namespaces: newMap(),
classes: newMap(),
};
namespace.methods = map(
symbol.methods,
partial(convertMethod, libName, namespace)
);
namespace.fields = map(
symbol.properties,
partial(convertField, libName, namespace)
);
namespace.events = map(
symbol.events,
partial(convertEvent, libName, namespace)
);
return namespace;
}
Example #4
Source File: convert.ts From ui5-language-assistant with Apache License 2.0 | 6 votes |
function convertInterface(
libName: string,
symbol: apiJson.InterfaceSymbol
): model.UI5Interface {
const base = convertSymbol(libName, symbol);
const interfacee: model.UI5Interface = {
...base,
kind: "UI5Interface",
events: [],
methods: [],
};
interfacee.events = map(
symbol.events,
partial(convertEvent, libName, interfacee)
);
interfacee.methods = map(
symbol.methods,
partial(convertMethod, libName, interfacee)
);
return interfacee;
}
Example #5
Source File: convert.ts From ui5-language-assistant with Apache License 2.0 | 6 votes |
function convertEnum(
libName: string,
symbol: apiJson.EnumSymbol
): model.UI5Enum {
const base = convertSymbol(libName, symbol);
const enumm: model.UI5Enum = {
...base,
kind: "UI5Enum",
fields: [],
};
enumm.fields = map(
symbol.properties,
partial(convertEnumValue, libName, enumm)
);
return enumm;
}
Example #6
Source File: flatten-members.ts From ui5-language-assistant with Apache License 2.0 | 5 votes |
flattenAggregations = partial(
flattenMembers,
(_) => _.aggregations
)
Example #7
Source File: namespace-spec.ts From ui5-language-assistant with Apache License 2.0 | 5 votes |
expectNamespaceValuesSuggestions = partial(expectSuggestions, (_) => {
expect(_.type).to.equal("UI5NamespacesInXMLAttributeValue");
const namespaceSuggestion = _ as UI5NamespacesInXMLAttributeValueCompletion;
expectUI5Namespace(namespaceSuggestion.ui5Node);
expectXMLAttribute(namespaceSuggestion.astNode);
return ui5NodeToFQN(namespaceSuggestion.ui5Node);
})
Example #8
Source File: prop-event-assoc-spec.ts From ui5-language-assistant with Apache License 2.0 | 5 votes |
expectAttributesNames = partial(expectSuggestions, (_) => _.ui5Node.name)
Example #9
Source File: namespace-spec.ts From ui5-language-assistant with Apache License 2.0 | 5 votes |
expectNamespaceKeysSuggestions = partial(expectSuggestions, (_) => {
expect(_.type).to.equal("UI5NamespacesInXMLAttributeKey");
const namespaceInKey = _ as UI5NamespacesInXMLAttributeKeyCompletion;
expectUI5Namespace(namespaceInKey.ui5Node);
expectXMLAttribute(namespaceInKey.astNode);
return ui5NodeToFQN(namespaceInKey.ui5Node);
})
Example #10
Source File: convert.ts From ui5-language-assistant with Apache License 2.0 | 5 votes |
function convertClass(
libName: string,
symbol: apiJson.ClassSymbol
): model.UI5Class {
const base = convertSymbol(libName, symbol);
const clazz: model.UI5Class = {
...base,
kind: "UI5Class",
abstract: symbol.abstract ?? false,
ctor: undefined,
extends: undefined, // Filled later
implements: [], // Filled later
aggregations: [],
associations: [],
events: [],
methods: [],
properties: [],
fields: [],
defaultAggregation: undefined, // Filled later
};
if (symbol["ui5-metadata"] !== undefined) {
clazz.aggregations = map(symbol["ui5-metadata"].aggregations, (_) =>
convertAggregation(libName, _, clazz)
);
clazz.associations = map(symbol["ui5-metadata"].associations, (_) =>
convertAssociation(libName, _, clazz)
);
clazz.properties = map(
symbol["ui5-metadata"].properties,
partial(convertProperty, libName, clazz)
);
// Add special settings (for example: "id" from ManagedObject)
clazz.properties = clazz.properties.concat(
map(
symbol["ui5-metadata"].specialSettings,
partial(convertProperty, libName, clazz)
)
);
}
// Due to unfortunate naming, if not defined in the json, symbol.constructor will be a javascript function
clazz.ctor =
symbol.constructor === undefined || isFunction(symbol.constructor)
? undefined
: convertConstructor(libName, clazz, symbol.constructor);
clazz.events = map(symbol.events, partial(convertEvent, libName, clazz));
clazz.methods = map(symbol.methods, partial(convertMethod, libName, clazz));
// The "properties" directly under the class symbol are displayed as "fields" in the SDK and are not considered properties
clazz.fields = map(
symbol.properties,
partial(convertProperty, libName, clazz)
);
return clazz;
}
Example #11
Source File: flatten-members.ts From ui5-language-assistant with Apache License 2.0 | 5 votes |
flattenAssociations = partial(
flattenMembers,
(_) => _.associations
)
Example #12
Source File: flatten-members.ts From ui5-language-assistant with Apache License 2.0 | 5 votes |
flattenEvents = partial(flattenMembers, (_) => _.events)
Example #13
Source File: flatten-members.ts From ui5-language-assistant with Apache License 2.0 | 5 votes |
flattenProperties = partial(flattenMembers, (_) => _.properties)
Example #14
Source File: unknown-attribute-key-spec.ts From ui5-language-assistant with Apache License 2.0 | 4 votes |
describe("the unknown attribute name validation", () => {
let ui5SemanticModel: UI5SemanticModel;
before(async () => {
ui5SemanticModel = await generateModel({
version: "1.74.0",
modelGenerator: generate,
});
});
context("true positive scenarios", () => {
let assertSingleIssue: (xmlSnippet: string, message: string) => void;
before(() => {
assertSingleIssue = partial(
assertSingleIssueBase,
ui5SemanticModel,
{
attribute: [validators.validateUnknownAttributeKey],
},
"UnknownAttributeKey",
"error"
);
});
it("will detect an invalid attribute key in root class element", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
?busy_TYPO?="true">
</mvc:View>`,
"Unknown attribute key: busy_TYPO"
);
});
it("will detect an invalid attribute key when the key starts with :", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
?:busy?="true">
</mvc:View>`,
"Unknown attribute key: :busy"
);
});
it("will detect an invalid attribute key when the key ends with :", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
?busy:?="true">
</mvc:View>`,
"Unknown attribute key: busy:"
);
});
it("will detect an invalid attribute key in non-root class element", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<mvc:content>
<List ?TYPO?=""></List>
</mvc:content>
</mvc:View>`,
"Unknown attribute key: TYPO"
);
});
it("will detect an invalid attribute key when the attribute doesn't have a value", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
?busy_TYPO? >
</mvc:View>`,
"Unknown attribute key: busy_TYPO"
);
});
it("will detect an invalid attribute key in aggregation element", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<mvc:content ?TYPO?="">
<List></List>
</mvc:content>
</mvc:View>`,
"Unknown attribute key: TYPO"
);
});
it("will detect an invalid xmlns attribute key element - no prefix", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
?xmlns:?="my.ns">
</mvc:View>`,
"Unknown attribute key: xmlns:"
);
});
it("will detect an invalid xmlns attribute key element - more than 1 colon", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
?xmlns:m:1?="sap.m">
</mvc:View>`,
"Unknown attribute key: xmlns:m:1"
);
});
it("will detect 'stashed' as invalid in aggregation element", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<mvc:content ?stashed?="">
<List></List>
</mvc:content>
</mvc:View>`,
"Unknown attribute key: stashed"
);
});
it("will detect 'binding' as invalid in aggregation element", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<mvc:content ?binding?="">
<List></List>
</mvc:content>
</mvc:View>`,
"Unknown attribute key: binding"
);
});
it("will detect 'class' as invalid in aggregation element", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<mvc:content ?class?="">
<List></List>
</mvc:content>
</mvc:View>`,
"Unknown attribute key: class"
);
});
it("will detect 'require' as invalid attribute when it's not in the core or template namespace", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
?mvc:require?="">
</mvc:View>`,
"Unknown attribute key: mvc:require"
);
});
it("will detect a non-public attribute key in class element", () => {
// Check that the property exists in the model
const ui5Class = ui5SemanticModel.classes["sap.uxap.AnchorBar"];
expectExists(ui5Class, "sap.uxap.AnchorBar");
const _selectProperty = find(ui5Class.aggregations, ["name", "_select"]);
expectExists(_selectProperty, "_select");
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:uxap="sap.uxap">
<mvc:content>
<uxap:AnchorBar ?_select?=""></uxap:AnchorBar>
</mvc:content>
</mvc:View>`,
"Unknown attribute key: _select"
);
});
});
context("negative edge cases", () => {
let assertNoIssues: (xmlSnippet: string) => void;
before(() => {
assertNoIssues = partial(assertNoIssuesBase, ui5SemanticModel, {
attribute: [validators.validateUnknownAttributeKey],
});
});
context("class tag", () => {
it("will not detect an issue when the attribute is a property", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
busy="true">
</mvc:View>`);
});
it("will not detect an issue when the attribute is an event", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
afterInit="true">
</mvc:View>`);
});
it("will not detect an issue when the attribute is an association", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<mvc:content>
<m:List ariaLabelledBy="abc"></m:List>
</mvc:content>
</mvc:View>`);
});
it("will not detect an issue when the attribute is an aggrgation", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
content="{model>elements}">
</mvc:View>`);
});
context("special attributes", () => {
it("will not detect an issue when the attribute is 'core:require'", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:core="sap.ui.core"
core:require="">
</mvc:View>`);
});
it("will not detect an issue when the attribute is 'sap.ui.dt:designtime'", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:dt="sap.ui.dt"
dt:designtime="">
</mvc:View>`);
});
it("will not detect an issue when the attribute is 'template:require'", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:template="http://schemas.sap.com/sapui5/extension/sap.ui.core.template/1"
template:require="">
</mvc:View>`);
});
it("will not detect an issue when the attribute is 'binding'", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
binding="{}">
</mvc:View>`);
});
it("will not detect an issue when the attribute is 'class'", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
class="small">
</mvc:View>`);
});
it("will not detect an issue when the attribute namespace is custom data", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:custom="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1"
custom:unknownattr="">
</mvc:View>`);
});
it("will not detect an issue when the attribute is 'stashed' on sap.uxap.ObjectPageLazyLoader", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:uxap="sap.uxap">
<mvc:content>
<uxap:ObjectPageLazyLoader stashed="true"></uxap:ObjectPageLazyLoader>
</mvc:content>
</mvc:View>`);
});
it("will not detect an issue when the attribute is xmlns (default)", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc">
<mvc:content>
<List xmlns="sap.m"></List>
</mvc:content>
</mvc:View>`);
});
it("will not detect an issue when the attribute is xmlns (with name)", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"">
<mvc:content>
<m:List xmlns:m="sap.m"></m:List>
</mvc:content>
</mvc:View>`);
});
});
});
context("aggregation tag", () => {
it("will not detect an issue when the attribute is 'core:require'", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:core="sap.ui.core">
<mvc:content core:require="">
</mvc:content>
</mvc:View>`);
});
it("will not detect an issue when the attribute is 'sap.ui.dt:designtime'", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:dt="sap.ui.dt">
<mvc:content dt:designtime=""></mvc:content>
</mvc:View>`);
});
it("will not detect an issue when the attribute is 'template:require'", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:template="http://schemas.sap.com/sapui5/extension/sap.ui.core.template/1">
<mvc:content template:require=""></mvc:content>
</mvc:View>`);
});
it("will not detect an issue when the attribute namespace is custom data", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:custom="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1">
<mvc:content custom:unknownattr=""></mvc:content>
</mvc:View>`);
});
it("will not detect an issue when the attribute is xmlns (default)", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"">
<mvc:content xmlns="sap.m">
</mvc:content>
</mvc:View>`);
});
it("will not detect an issue when the attribute is xmlns (with name)", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"">
<mvc:content xmlns:m="sap.m">
</mvc:content>
</mvc:View>`);
});
});
context("unknown tag", () => {
it("will not detect an issue when the attribute name is unknown for tag starting with lowecase", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<mvc:content_TYPO TYPO="">
</mvc:content_TYPO>
</mvc:View>`);
});
it("will not detect an issue when the attribute name is unknown for tag starting with uppercase", () => {
assertNoIssues(`
<mvc:View
xmlns:mvc="sap.ui.core.mvc">
<mvc:content>
<List_TYPO TYPO=""></List_TYPO>
</mvc:content>
</mvc:View>`);
});
it("will not detect an issue when the attribute name is unknown for tag in known namespace", () => {
assertNoIssues(`
<mvc:View_TYPO
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
busy_TYPO="true">
</mvc:View_TYPO>`);
});
});
context("non-reproducible unit tests", () => {
it("will not detect an issue when the attribute doesn't have a key", () => {
const xmlSnippet = `
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
attr="">
</mvc:View>`;
const { cst, tokenVector } = parse(xmlSnippet);
const ast = buildAst(cst as DocumentCstNode, tokenVector);
const attr = ast.rootElement?.attributes[0];
expectExists(attr, "attr");
const attrWithoutKey = {
...attr,
key: null,
};
const issues = validators.validateUnknownAttributeKey(
attrWithoutKey,
ui5SemanticModel
);
expect(issues).to.be.empty;
});
});
});
});
Example #15
Source File: use-of-depracated-attribute-spec.ts From ui5-language-assistant with Apache License 2.0 | 4 votes |
describe("the use of deprecated attribute validation", () => {
let ui5SemanticModel: UI5SemanticModel;
before(async () => {
ui5SemanticModel = await generateModel({
version: "1.74.0",
modelGenerator: generate,
});
});
context("true positive scenarios", () => {
function assertSingleIssue(
xmlSnippet: string,
message: string,
issueKind: string
) {
return assertSingleIssueBase(
ui5SemanticModel,
{
attribute: [validators.validateUseOfDeprecatedAttribute],
},
issueKind,
"warn",
xmlSnippet,
message
);
}
it("will detect usage of a deprecated attribute property", () => {
const pageClass = ui5SemanticModel.classes["sap.m.Page"];
const navButtonTextProperty = find(
pageClass.properties,
(_) => _.name === "navButtonText"
);
assertSingleIssue(
`<mvc:View xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc">
<m:Page ?navButtonText?="">
</m:Page>
</mvc:View>`,
buildDeprecatedIssueMessage({
symbol: navButtonTextProperty as DeprecatedUI5Symbol,
model: ui5SemanticModel,
}),
"UseOfDeprecatedProperty"
);
});
it("will detect usage of a deprecated attribute event", () => {
const appClass = ui5SemanticModel.classes["sap.m.App"];
const orientationChangeEvent = find(
appClass.events,
(_) => _.name === "orientationChange"
);
assertSingleIssue(
`<mvc:View xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc">
<m:App ?orientationChange?="">
</m:App>
</mvc:View>`,
buildDeprecatedIssueMessage({
symbol: orientationChangeEvent as DeprecatedUI5Symbol,
model: ui5SemanticModel,
}),
"UseOfDeprecatedEvent"
);
});
it("will detect usage of a deprecated attribute association", () => {
const popoverClass = ui5SemanticModel.classes["sap.m.Popover"];
const leftButtonAssociation = find(
popoverClass.associations,
(_) => _.name === "leftButton"
);
assertSingleIssue(
`<mvc:View xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc">
<m:Popover ?leftButton?="">
</m:Popover>
</mvc:View>`,
buildDeprecatedIssueMessage({
symbol: leftButtonAssociation as DeprecatedUI5Symbol,
model: ui5SemanticModel,
}),
"UseOfDeprecatedAssociation"
);
});
it("will detect usage of a deprecated attribute aggregation", () => {
const genericTileClass = ui5SemanticModel.classes["sap.m.GenericTile"];
const iconAggregation = find(
genericTileClass.aggregations,
(_) => _.name === "icon"
);
assertSingleIssue(
`<mvc:View xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc">
<m:GenericTile ?icon?="">
</m:GenericTile>
</mvc:View>`,
buildDeprecatedIssueMessage({
symbol: iconAggregation as DeprecatedUI5Symbol,
model: ui5SemanticModel,
}),
"UseOfDeprecatedAggregation"
);
});
});
context("negative edge cases", () => {
let assertNoIssues: (xmlSnippet: string) => void;
before(() => {
assertNoIssues = partial(assertNoIssuesBase, ui5SemanticModel, {
attribute: [validators.validateUseOfDeprecatedAttribute],
});
});
it("will not detect an issue when the attribute key has not been deprecated", () => {
assertNoIssues(
`<mvc:View xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc" busy="true">
</mvc:View`
);
});
it("will not detect an issue when the enclosing tag is not a UI5 class", () => {
assertNoIssues(
`<mvc:View1
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
busy="true">
</mvc:View1>`
);
});
it("will not detect an issue when the attribute is part of a UI5 Class tag but not a recognized property", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
busy1="untrue">
</mvc:View>`
);
});
});
context("non-reproducible unit tests", () => {
it("will not detect an issue when the attribute doesn't have a key", () => {
const xmlSnippet = `
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
attr="">
</mvc:View>`;
const { cst, tokenVector } = parse(xmlSnippet);
const ast = buildAst(cst as DocumentCstNode, tokenVector);
const attr = ast.rootElement?.attributes[0];
expectExists(attr, "attr");
const attrWithoutKey = {
...attr,
key: null,
};
const issues = validators.validateUseOfDeprecatedAttribute(
attrWithoutKey,
ui5SemanticModel
);
expect(issues).to.be.empty;
});
});
});
Example #16
Source File: cardinality-of-aggregation-spec.ts From ui5-language-assistant with Apache License 2.0 | 4 votes |
describe("the cardinality aggregation validation", () => {
let ui5SemanticModel: UI5SemanticModel;
before(async () => {
ui5SemanticModel = await generateModel({
version: "1.74.0",
modelGenerator: generate,
});
});
context("true positive scenarios", () => {
let assertSingleIssue: (xmlSnippet: string, message: string) => void;
before(() => {
assertSingleIssue = partial(
assertSingleIssueBase,
ui5SemanticModel,
{
element: [validators.validateExplicitAggregationCardinality],
},
"InvalidAggregationCardinality",
"error"
);
});
it("will detect aggregation with cardinality of 0..1 with more than one element", () => {
assertSingleIssue(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<m:Panel>
<m:headerToolbar>
<m:Toolbar></m:Toolbar>
<?m:Toolbar?></m:Toolbar>
</m:headerToolbar>
</m:Panel>
</mvc:View>`,
buildMessage(INVALID_AGGREGATION_CARDINALITY.msg, "headerToolbar")
);
});
it("multi tags with single aggreation - will detect aggregation with more elements than its cardinality allows", () => {
assertSingleIssue(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<m:Panel>
<m:headerToolbar>
<m:Toolbar></m:Toolbar>
</m:headerToolbar>
<m:headerToolbar>
<?m:Toolbar?></m:Toolbar>
</m:headerToolbar>
</m:Panel>
</mvc:View>`,
buildMessage(INVALID_AGGREGATION_CARDINALITY.msg, "headerToolbar")
);
});
it("will detect aggregation with cardinality of 0..1 with more than one element - element without name", () => {
assertSingleIssue(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<m:Panel>
<m:headerToolbar>
<m:Toolbar></m:Toolbar>
</m:headerToolbar>
<m:headerToolbar>
?<></>?
</m:headerToolbar>
</m:Panel>
</mvc:View>`,
buildMessage(INVALID_AGGREGATION_CARDINALITY.msg, "headerToolbar")
);
});
});
context("negative edge cases", () => {
let assertNoIssues: (xmlSnippet: string) => void;
before(() => {
assertNoIssues = partial(assertNoIssuesBase, ui5SemanticModel, {
element: [validators.validateExplicitAggregationCardinality],
});
});
it("will not detect an issue when there is an aggregation with only one element", () => {
assertNoIssues(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<m:Panel>
<m:headerToolbar>
<m:Toolbar></m:Toolbar>
</m:headerToolbar>
</m:Panel>
</mvc:View>`
);
});
it("will not detect an issue when there is an aggregation with cardinality of 0..n", () => {
assertNoIssues(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<m:Panel>
<content>
<m:Toolbar></m:Toolbar>
<m:Toolbar></m:Toolbar>
</content>
</m:Panel>
</mvc:View>`
);
});
});
});
Example #17
Source File: non-stable-id-spec.ts From ui5-language-assistant with Apache License 2.0 | 4 votes |
describe("the use of non stable id validation", () => {
let ui5SemanticModel: UI5SemanticModel;
before(async () => {
ui5SemanticModel = await generateModel({
version: "1.74.0",
modelGenerator: generate,
});
});
context("true positive scenarios", () => {
let assertSingleIssue: (xmlSnippet: string, message: string) => void;
before(() => {
assertSingleIssue = partial(
assertSingleIssueBase,
ui5SemanticModel,
{
element: [validators.validateNonStableId],
},
"NonStableIDIssue",
"error"
);
});
it("will detect missing stable id in non-whitelisted UI5 class", () => {
assertSingleIssue(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<?m:Panel?>
</m:Panel>
</mvc:View>`,
buildMessage(NON_STABLE_ID.msg, "Panel")
);
});
it("will detect missing stable id in custom control", () => {
assertSingleIssue(
`<mvc:View xmlns:uxap="sap.uxap"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons" xmlns:custom="sap.m">
<?custom:Button?>
</custom:Button>
</mvc:View>`,
buildMessage(NON_STABLE_ID.msg, "Button")
);
});
it("will detect missing stable id in root level custom control", () => {
assertSingleIssue(
`<?custom:View?
xmlns:custom="foo.bar"
xmlns="bar.foo">
<Button id="dummy-id">
</Button>
</custom:View>`,
buildMessage(NON_STABLE_ID.msg, "View")
);
});
it("will detect missing stable id in whitelisted root class when it's not in the root", () => {
assertSingleIssue(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<?mvc:View?>
</mvc:View>
</mvc:View>`,
buildMessage(NON_STABLE_ID.msg, "View")
);
});
it("will detect missing stable in sub element when the parent element has attribute sap.ui.dt:designtime='not-adaptable'", () => {
assertSingleIssue(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons"
xmlns:sap.ui.dt="sap.ui.dt">
<m:Panel sap.ui.dt:designtime="not-adaptable">
<?m:Button?></m:Button>
</m:Panel>
</mvc:View>`,
buildMessage(NON_STABLE_ID.msg, "Button")
);
});
it("will detect missing stable id when there is null id attribute value", () => {
assertSingleIssue(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<?m:Panel? id=>
</m:Panel>
</mvc:View>`,
buildMessage(NON_STABLE_ID.msg, "Panel")
);
});
it("will detect missing stable id when there is empty id attribute value", () => {
assertSingleIssue(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<?m:Panel? id="">
</m:Panel>
</mvc:View>`,
buildMessage(NON_STABLE_ID.msg, "Panel")
);
});
});
context("negative edge cases", () => {
let assertNoIssues: (xmlSnippet: string) => void;
before(() => {
assertNoIssues = partial(assertNoIssuesBase, ui5SemanticModel, {
element: [validators.validateNonStableId],
});
});
it("will not detect an issue for a root-whitelisted UI5 class", () => {
assertNoIssues(
`<!-- sap.ui.core.mvc.View is whitlisted root class -->
<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
</mvc:View>`
);
});
it("will not detect an issue for a root-whitelisted UI5 class - core ns", () => {
assertNoIssues(
`<!-- sap.ui.core.FragmentDefinition is whitlisted root class -->
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core">
</core:FragmentDefinition>`
);
});
it("will not detect an issue for a whitelisted UI5 class", () => {
assertNoIssues(
`<mvc:View xmlns:core="sap.ui.core" xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<m:Button id="yyy">
<m:customData>
<core:CustomData></core:CustomData>
</m:customData>
</m:Button>
</mvc:View>`
);
});
it("will not detect an issue for a control with attribute sap.ui.dt:designtime='not-adaptable'", () => {
assertNoIssues(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons"
xmlns:sap.ui.dt="sap.ui.dt">
<m:Panel sap.ui.dt:designtime="not-adaptable">
</m:Panel>
</mvc:View>`
);
});
it("will not detect an issue for a control and it's sub elements when it contains attribute sap.ui.dt:designtime='not-adaptable-tree'", () => {
assertNoIssues(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons"
xmlns:sap.ui.dt="sap.ui.dt">
<m:Panel sap.ui.dt:designtime="not-adaptable-tree">
<m:Button>
</m:Button>
</m:Panel>
</mvc:View>`
);
});
it("will not detect an issue for tag without a name", () => {
assertNoIssues(
`< >
</View>`
);
});
});
});
Example #18
Source File: type-of-aggregation-spec.ts From ui5-language-assistant with Apache License 2.0 | 4 votes |
describe("the type aggregation validation", () => {
let ui5SemanticModel: UI5SemanticModel;
before(async () => {
ui5SemanticModel = await generateModel({
version: "1.74.0",
modelGenerator: generate,
});
});
context("true positive scenarios", () => {
let assertSingleIssue: (xmlSnippet: string, message: string) => void;
before(() => {
assertSingleIssue = partial(
assertSingleIssueBase,
ui5SemanticModel,
{
element: [validators.validateAggregationType],
},
"InvalidAggregationType",
"error"
);
});
it("will detect mismatch of class to explicit aggregation of 'UI5Class' type", () => {
assertSingleIssue(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<m:Panel>
<m:headerToolbar>
<?Button?></Button>
</m:headerToolbar>
</m:Panel>
</mvc:View>`,
buildMessage(
INVALID_AGGREGATION_TYPE.msg,
"Button",
"headerToolbar",
"Toolbar"
)
);
});
it("will detect mismatch of class to default aggregation of 'UI5Interface' type", () => {
assertSingleIssue(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<m:Panel>
<?ToolbarSeparator?></ToolbarSeparator>
</m:Panel>
</mvc:View>`,
buildMessage(
INVALID_AGGREGATION_TYPE.msg,
"ToolbarSeparator",
"content",
"Control"
)
);
});
it("will detect mismatch of class to explicit aggregation of 'UI5Class' type", () => {
assertSingleIssue(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<m:Page>
<m:footer>
<!-- The class "Toolbar" is under the aggregation "footer" and must match the type "IBar" -->
<?Toolbar?></Toolbar>
</m:footer>
</m:Page>
</mvc:View>`,
buildMessage(INVALID_AGGREGATION_TYPE.msg, "Toolbar", "footer", "IBar")
);
});
});
context("negative edge cases", () => {
let assertNoIssues: (xmlSnippet: string) => void;
before(() => {
assertNoIssues = partial(assertNoIssuesBase, ui5SemanticModel, {
element: [validators.validateAggregationType],
});
});
it("will not detect an issue when the class is under the default aggregation and matching its type", () => {
assertNoIssues(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<m:Shell></m:Shell>
</mvc:View>`
);
});
it("will not detect an issue when the class is under non-ui5 aggregation", () => {
assertNoIssues(
`<mvc:View xmlns:uxap="sap.uxap" xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.ui.commons">
<UnknownTag>
<Toolbar></Toolbar>
</UnknownTag>
</mvc:View>`
);
});
it("will not detect an issue when the class is under explicit aggregation when the aggregartion type is not a UI5Class or UI5Interface", () => {
const clonedModel = cloneDeep(ui5SemanticModel);
const viewClass = clonedModel.classes["sap.ui.core.mvc.View"];
const contentAggregation = find(
viewClass.aggregations,
(_) => _.name === "content"
) as UI5Aggregation;
expect(contentAggregation).to.exist;
contentAggregation.type = undefined;
viewClass.aggregations = [contentAggregation];
const xmlSnippet = `
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<mvc:content>
<Shell></Shell>
</mvc:content>
</mvc:View>`;
assertNoIssuesBase(
clonedModel,
{
element: [validators.validateAggregationType],
},
xmlSnippet
);
});
it("will not detect an issue when the class is a `sap.ui.core.Fragment", () => {
assertNoIssues(
`<mvc:View xmlns:uxap="sap.uxap"
xmlns:m="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns:core="sap.ui.core">
<m:Page>
<m:content>
<core:Fragment fragmentName="Fragment1" type="XML" />
</m:content>
</m:Page>
</mvc:View>`
);
});
});
});
Example #19
Source File: unknown-tag-name-spec.ts From ui5-language-assistant with Apache License 2.0 | 4 votes |
describe("the unknown tag name validation", () => {
let ui5SemanticModel: UI5SemanticModel;
before(async () => {
ui5SemanticModel = await generateModel({
version: "1.74.0",
modelGenerator: generate,
});
});
context("true positive scenarios", () => {
let assertSingleIssue: (xmlSnippet: string, message: string) => void;
before(() => {
assertSingleIssue = partial(
assertSingleIssueBase,
ui5SemanticModel,
{
element: [validators.validateUnknownTagName],
},
"UnknownTagName",
"error"
);
});
context("tag with namespace", () => {
it("will detect an invalid class name in root tag", () => {
assertSingleIssue(
`<?mvc:View_TYPO?
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
</mvc:View_TYPO>`,
buildMessage(UNKNOWN_CLASS_IN_NS.msg, "View_TYPO", "sap.ui.core.mvc")
);
});
it("will detect an invalid class name under class that has default aggregation", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m">
<?m:Button_TYPO?>
</m:Button_TYPO>
</mvc:View>`,
buildMessage(UNKNOWN_CLASS_IN_NS.msg, "Button_TYPO", "sap.m")
);
});
it("will detect an invalid class name under class that doesn't have a default aggregation", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m">
<m:SplitApp>
<?m:Button_TYPO?>
</m:Button_TYPO>
</m:SplitApp>
</mvc:View>`,
buildMessage(
UNKNOWN_TAG_NAME_IN_NS_UNDER_CLASS.msg,
"Button_TYPO",
"sap.m",
"sap.m.SplitApp"
)
);
});
it("will detect an invalid class name under aggregation", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m">
<mvc:content>
<?m:Button_TYPO?>
</m:Button_TYPO>
</mvc:content>
</mvc:View>`,
buildMessage(UNKNOWN_CLASS_IN_NS.msg, "Button_TYPO", "sap.m")
);
});
it("will detect an invalid aggregation when it's in the wrong namespace", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m">
<?m:content?>
</mv:content>
</mvc:View>`,
buildMessage(UNKNOWN_CLASS_IN_NS.msg, "content", "sap.m")
);
});
it("will detect an invalid class name under aggregation in the same namespace", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc">
<mvc:content>
<?mvc:Button_TYPO?>
</mvc:Button_TYPO>
</mvc:content>
</mvc:View>`,
buildMessage(
UNKNOWN_CLASS_IN_NS.msg,
"Button_TYPO",
"sap.ui.core.mvc"
)
);
});
it("will detect an invalid aggregation name under known class tag without default aggregation", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m">
<m:SplitApp>
<?m:content_TYPO?>
</m:content_TYPO>
</m:SplitApp>
</mvc:View>`,
buildMessage(
UNKNOWN_TAG_NAME_IN_NS_UNDER_CLASS.msg,
"content_TYPO",
"sap.m",
"sap.m.SplitApp"
)
);
});
it("will detect an issue for unknown name under unknown class in a known namespace", () => {
const xmlSnippet = `
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m">
<?m:SplitApp_TYPO?>
<?m:Button_TYPO?>
</m:Button_TYPO>
</m:SplitApp_TYPO>
</mvc:View>`;
const expectedRanges = computeExpectedRanges(xmlSnippet);
testValidationsScenario({
model: ui5SemanticModel,
xmlText: xmlSnippet,
validators: { element: [validators.validateUnknownTagName] },
assertion: (issues) => {
expect(issues).to.deep.equalInAnyOrder([
{
kind: "UnknownTagName",
message: buildMessage(
UNKNOWN_CLASS_IN_NS.msg,
"SplitApp_TYPO",
"sap.m"
),
offsetRange: expectedRanges[0],
severity: "error",
},
{
kind: "UnknownTagName",
message: buildMessage(
UNKNOWN_TAG_NAME_IN_NS.msg,
"Button_TYPO",
"sap.m"
),
offsetRange: expectedRanges[1],
severity: "error",
},
]);
},
});
});
});
context("tag without namespace", () => {
context("when default namespace is not defined", () => {
it("will detect an invalid class name in root tag", () => {
assertSingleIssue(
`<?View?>
</View>`,
buildMessage(UNKNOWN_CLASS_WITHOUT_NS.msg, "View")
);
});
it("will detect an invalid class name under known aggregation tag", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc">
<mvc:content>
<?List?></List>
</mvc:content>
</mvc:View>`,
buildMessage(UNKNOWN_CLASS_WITHOUT_NS.msg, "List")
);
});
it("will detect an invalid class or aggregation name under known class tag with default aggregation", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc">
<?List?></List>
</mvc:View>`,
buildMessage(
UNKNOWN_TAG_NAME_IN_CLASS.msg,
"List",
"sap.ui.core.mvc.View"
)
);
});
it("will detect an invalid aggregation namespace under known class tag without default aggregation", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m">
<m:SplitApp>
<?content?>
</content>
</m:SplitApp>
</mvc:View>`,
buildMessage(
UNKNOWN_AGGREGATION_IN_CLASS_DIFF_NAMESPACE.msg,
"content",
"sap.m.SplitApp"
)
);
});
it("will detect an issue for unknown name under unknown class in non-default non-ui5 namespace when name starts with uppercase", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:typo="sap.m_TYPO">
<typo:SplitApp>
<?Button_TYPO?>
</Button_TYPO>
</typo:SplitApp>
</mvc:View>`,
buildMessage(UNKNOWN_TAG_NAME_NO_NS.msg, "Button_TYPO")
);
});
});
context("when default namespace is a ui5 namespace", () => {
it("will detect an issue for unknown name under unknown class in the default namespace", () => {
const xmlSnippet = `
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<?SplitApp_TYPO?>
<?Button_TYPO?>
</Button_TYPO>
</SplitApp_TYPO>
</mvc:View>`;
const expectedRanges = computeExpectedRanges(xmlSnippet);
testValidationsScenario({
model: ui5SemanticModel,
xmlText: xmlSnippet,
validators: { element: [validators.validateUnknownTagName] },
assertion: (issues) => {
expect(issues).to.deep.equalInAnyOrder([
{
kind: "UnknownTagName",
message: buildMessage(
UNKNOWN_TAG_NAME_IN_NS_UNDER_CLASS.msg,
"SplitApp_TYPO",
"sap.m",
"sap.ui.core.mvc.View"
),
offsetRange: expectedRanges[0],
severity: "error",
},
{
kind: "UnknownTagName",
message: buildMessage(
UNKNOWN_TAG_NAME_IN_NS.msg,
"Button_TYPO",
"sap.m"
),
offsetRange: expectedRanges[1],
severity: "error",
},
]);
},
});
});
});
});
context("when default namespace is a ui5 namespace", () => {
it("will detect an invalid class name in root tag", () => {
assertSingleIssue(
`<?View_TYPO?
xmlns="sap.ui.core.mvc">
</View_TYPO>`,
buildMessage(UNKNOWN_CLASS_IN_NS.msg, "View_TYPO", "sap.ui.core.mvc")
);
});
it("will detect an invalid class name under known aggregation tag", () => {
assertSingleIssue(
`<View
xmlns="sap.ui.core.mvc">
<content>
<?List_TYPO?></List_TYPO>
</content>
</View>`,
buildMessage(UNKNOWN_CLASS_IN_NS.msg, "List_TYPO", "sap.ui.core.mvc")
);
});
it("will detect an invalid class or aggregation name under known class tag with default aggregation", () => {
assertSingleIssue(
`<View
xmlns="sap.ui.core.mvc">
<?List_TYPO?></List_TYPO>
</View>`,
buildMessage(
UNKNOWN_TAG_NAME_IN_NS_UNDER_CLASS.msg,
"List_TYPO",
"sap.ui.core.mvc",
"sap.ui.core.mvc.View"
)
);
});
it("will detect an invalid aggregation name under known class tag without default aggregation", () => {
assertSingleIssue(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<SplitApp>
<?content_TYPO?>
</content_TYPO>
</SplitApp>
</mvc:View>`,
buildMessage(
UNKNOWN_AGGREGATION_IN_CLASS.msg,
"content_TYPO",
"sap.m.SplitApp"
)
);
});
});
});
context("negative edge cases", () => {
let assertNoIssues: (xmlSnippet: string) => void;
before(() => {
assertNoIssues = partial(assertNoIssuesBase, ui5SemanticModel, {
element: [validators.validateUnknownTagName],
});
});
context("tag with namespace", () => {
context("non-ui5 namespace", () => {
it("will not detect an issue when namespace is unknown", () => {
assertNoIssues(
`<mvc:View_TYPO
xmlns:mvc="sap.ui.core.mvc_TYPO"
xmlns="sap.m">
</mvc:View_TYPO>`
);
});
it("will not detect an issue when namespace is xhtml", () => {
assertNoIssues(
`<mvc:View_TYPO
xmlns:mvc="http://www.w3.org/1999/xhtml"
xmlns="sap.m">
</mvc:View_TYPO>`
);
});
it("will not detect an issue when namespace is not defined in xmlns attribute", () => {
assertNoIssues(
`<mvc:View_TYPO
xmlns="sap.m">
</mvc:View_TYPO>`
);
});
});
context("ui5 namespace", () => {
let assertSingleIssue: (xmlSnippet: string, message: string) => void;
before(() => {
assertSingleIssue = partial(
assertSingleIssueBase,
ui5SemanticModel,
{
element: [validators.validateUnknownTagName],
},
"UnknownTagName",
"error"
);
});
it("will not detect an issue for known class in the root tag", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
</mvc:View>`
);
});
it("will not detect an issue for sap.ui.core.FragmentDefinition in the root tag", () => {
assertNoIssues(
`<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core">
<Label text="These controls are within one multi-root Fragment:" />
<Input />
<Button text="Still in the same Fragment" />
</core:FragmentDefinition>`
);
});
it("will not detect an issue for known aggregation in a different namespace prefix that references the same namespace", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:mvc2="sap.ui.core.mvc">
<mvc2:content>
</mvc2:content>
</mvc:View>`
);
});
it("will not detect an issue for known class under class that has default aggregation", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m">
<m:Button>
</m:Button>
</mvc:View>`
);
});
it("will not detect an issue for known class under class that doesn't have a default aggregation", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m">
<m:SplitApp>
<m:Button>
</m:Button>
</m:SplitApp>
</mvc:View>`
);
});
it("will not detect an issue for known class under aggregation", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m">
<mvc:content>
<m:Button>
</m:Button>
</mvc:content>
</mvc:View>`
);
});
it("will not detect an issue for known class under tag in unknown namespace", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m"
xmlns:customns="customns">
<customns:SplitApp>
<m:Button>
</m:Button>
</customns:SplitApp>
</mvc:View>`
);
});
it("will not detect an issue for known class under tag in unknown default namespace", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m"
xmlns="customns">
<SplitApp>
<m:Button>
</m:Button>
</SplitApp>
</mvc:View>`
);
});
it("will not detect an issue for sap.ui.core.ExtensionPoint as top level element in sap.ui.core.mvc.View", () => {
assertNoIssues(
`<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns:core="sap.ui.core">
<core:ExtensionPoint name="extension1"/>
</mvc:View>`
);
});
it("will not detect an issue for sap.ui.core.ExtensionPoint as top level element in sap.ui.core.Fragment", () => {
assertNoIssues(
`<FragmentDefinition xmlns="sap.ui.core">
<ExtensionPoint name="extension1"/>
</FragmentDefinition>`
);
});
it("will not detect an issue for sap.ui.core.ExtensionPoint as nested element in sap.ui.core.mvc.View", () => {
assertNoIssues(
`<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns:core="sap.ui.core" xmlns:m="sap.m">
<m:Page>
<m:content>
<core:ExtensionPoint name="extension1"/>
</m:content>
</m:Page>
</mvc:View>`
);
});
it("will not detect an issue for sap.ui.core.ExtensionPoint as nested element in sap.ui.core.Fragment", () => {
assertNoIssues(
`<FragmentDefinition xmlns="sap.ui.core">
<m:Panel>
<m:content>
<core:ExtensionPoint name="extension1"/>
</m:content>
</m:Panel>
</FragmentDefinition>`
);
});
it("will detect an issue for sap.ui.core.ExtensionPoint in the root tag", () => {
assertSingleIssue(
`<?ExtensionPoint? name="extension1"></ExtensionPoint>`,
buildMessage(UNKNOWN_CLASS_WITHOUT_NS.msg, "ExtensionPoint")
);
});
});
});
context("tag without namespace", () => {
context("when default namespace is a ui5 namespace", () => {
it("will not detect an issue for known class in the root tag", () => {
assertNoIssues(
`<View
xmlns="sap.ui.core.mvc">
</View>`
);
});
it("will not detect an issue for sap.ui.core.FragmentDefinition in the root tag", () => {
assertNoIssues(
`<FragmentDefinition xmlns:m="sap.m" xmlns="sap.ui.core">
<m:Label text="These controls are within one multi-root Fragment:" />
<m:Input />
<m:Button text="Still in the same Fragment" />
</FragmentDefinition>`
);
});
it("will not detect an issue for known class under known aggregation tag", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<mvc:content>
<Button>
</Button>
</mvc:content>
</mvc:View>`
);
});
it("will not detect an issue for known class under known class tag with default aggregation", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<Button>
</Button>
</mvc:View>`
);
});
it("will not detect an issue for known class under known class tag without default aggregation", () => {
// This should be detected in a different validation
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<SplitApp>
<Button>
</Button>
</SplitApp>
</mvc:View>`
);
});
it("will not detect an issue for known aggregation under known class tag with default aggregation", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<mvc:content>
</mvc:content>
</mvc:View>`
);
});
it("will not detect an issue for known aggregation under known class tag without default aggregation", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<SplitApp>
<masterPages>
</masterPages>
</SplitApp>
</mvc:View>`
);
});
it("will not detect an issue for known class under tag in unknown namespace", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc_TYPO"
xmlns="sap.m">
<SplitApp>
</SplitApp>
</mvc:View>`
);
});
it("will not detect an issue for unknown name under unknown class in non-ui5 namespace", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:typo="sap.m_TYPO"
xmlns="sap.m">
<typo:SplitApp>
<typo:content_TYPO>
</typo:content_TYPO>
</typo:SplitApp>
</mvc:View>`
);
});
});
context("when default namespace is a non-ui5 namespace", () => {
it("will not detect an issue for unknown name in root tag", () => {
assertNoIssues(
`<View_TYPO
xmlns="sap.ui.core.mvc_TYPO">
</View_TYPO>`
);
});
it("will not detect an issue for unknown name under known aggregation tag", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m_TYPO">
<mvc:content>
<Button_TYPO>
</Button_TYPO>
</mvc:content>
</mvc:View>`
);
});
it("will not detect an issue for unknown name under known class tag with default aggregation", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m_TYPO">
<Button_TYPO>
</Button_TYPO>
</mvc:View>`
);
});
it("will not detect an issue for unknown name under known class tag without default aggregation", () => {
// The tag might still be allowed if it's not a class, e.g. template tags are allowed everywhere
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:m="sap.m"
xmlns="sap.m_TYPO">
<m:SplitApp>
<Button_TYPO>
</Button_TYPO>
</m:SplitApp>
</mvc:View>`
);
});
it("will not detect an issue for unknown name under unknown class in default non-ui5 namespace when name starts with lowercase", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m_TYPO">
<SplitApp>
<content_TYPO>
</content_TYPO>
</SplitApp>
</mvc:View>`
);
});
it("will not detect an issue for unknown name under unknown class in default non-ui5 namespace when name starts with uppercase", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m_TYPO">
<SplitApp>
<Button_TYPO>
</Button_TYPO>
</SplitApp>
</mvc:View>`
);
});
});
context("when default namespace is not defined", () => {
it("will not detect an issue for tag without a name", () => {
assertNoIssues(
`< >
</View>`
);
});
it("will not detect an issue for unknown name under unknown class in non-default non-ui5 namespace when name starts with lowercase", () => {
assertNoIssues(
`<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:typo="sap.m_TYPO">
<typo:SplitApp>
<typo:content_TYPO>
</typo:content_TYPO>
</typo:SplitApp>
</mvc:View>`
);
});
});
});
});
});
Example #20
Source File: use-of-deprecated-aggregation-spec.ts From ui5-language-assistant with Apache License 2.0 | 4 votes |
describe("the use of deprecated aggregation validation", () => {
let ui5SemanticModel: UI5SemanticModel;
before(async () => {
ui5SemanticModel = await generateModel({
version: "1.74.0",
modelGenerator: generate,
});
});
context("true positive scenarios", () => {
let assertSingleIssue: (xmlSnippet: string, message: string) => void;
before(() => {
assertSingleIssue = partial(
assertSingleIssueBase,
ui5SemanticModel,
{
element: [validators.validateUseOfDeprecatedAggregation],
},
"UseOfDeprecatedAggregation",
"warn"
);
});
it("will detect usage of a deprecated aggregation", () => {
const bubbleChart =
ui5SemanticModel.classes["sap.ca.ui.charts.BubbleChart"];
const contentAggregation = find(
bubbleChart.aggregations,
(_) => _.name === "content"
);
assertSingleIssue(
`<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns:charts="sap.ca.ui.charts">
<mvc:content>
<charts:BubbleChart>
<?charts:content?>
</charts:content>
</charts:BubbleChart>
</mvc:content>
</m:View>`,
buildDeprecatedIssueMessage({
symbol: contentAggregation as DeprecatedUI5Symbol,
model: ui5SemanticModel,
})
);
});
it("will detect usage of a deprecated aggregation with self closing syntax", () => {
const bubbleChart =
ui5SemanticModel.classes["sap.ca.ui.charts.BubbleChart"];
const contentAggregation = find(
bubbleChart.aggregations,
(_) => _.name === "content"
);
assertSingleIssue(
`<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns:charts="sap.ca.ui.charts">
<mvc:content>
<charts:BubbleChart>
<?charts:content?/>
</charts:BubbleChart>
</mvc:content>
</m:View>`,
buildDeprecatedIssueMessage({
symbol: contentAggregation as DeprecatedUI5Symbol,
model: ui5SemanticModel,
})
);
});
it("will detect usage of a deprecated aggregation in an unclosed element to enable **early warning** to users", () => {
const bubbleChart =
ui5SemanticModel.classes["sap.ca.ui.charts.BubbleChart"];
const contentAggregation = find(
bubbleChart.aggregations,
(_) => _.name === "content"
);
assertSingleIssue(
`<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns:charts="sap.ca.ui.charts">
<mvc:content>
<charts:BubbleChart>
<?charts:content?
</charts:BubbleChart>
</mvc:content>
</m:View>`,
buildDeprecatedIssueMessage({
symbol: contentAggregation as DeprecatedUI5Symbol,
model: ui5SemanticModel,
})
);
});
});
context("negative edge cases", () => {
let assertNoIssues: (xmlSnippet: string) => void;
before(() => {
assertNoIssues = partial(assertNoIssuesBase, ui5SemanticModel, {
element: [validators.validateUseOfDeprecatedAggregation],
});
});
it("will not detect an issue when the aggregation has not been deprecated", () => {
assertNoIssues(
`<mvc:View xmlns:m="sap.m" xmlns:mvc="sap.ui.core.mvc" xmlns:charts="sap.ca.ui.charts">
<mvc:content>
<m:Bar>
<!-- unlike sap.ca.ui.charts.BubbleChart.content, sap.ui.core.TooltipBase is not deprecated -->
<m:tooltip></m:tooltip>
</m:Bar>
</mvc:content>
</m:View>`
);
});
});
});
Example #21
Source File: ColumnComponent.tsx From next-basics with GNU General Public License v3.0 | 4 votes |
export function ColumnComponent(
props: ColumnComponentProps
): React.ReactElement {
const { column, field, rowIndex, hasLabel, formValue } = props;
const { label, name } = column;
const { name: fieldName, ...restField } = field;
const rowValue = formValue?.[rowIndex];
const labelNode = useMemo(
() => hasLabel && rowIndex === 0 && <div>{label}</div>,
[label, rowIndex, hasLabel]
);
const disabled = useMemo(
() => getRealValue(column.props?.disabled, [rowValue, rowIndex]),
[column.props?.disabled, rowValue, rowIndex]
);
const rules = useMemo(
() =>
column.rules?.map((rule) => {
if (typeof rule.validator === "function") {
return {
message: rule.message,
validator: partial(rule.validator, _, _, _, {
formValue,
rowValue,
rowIndex,
}),
};
}
if (rule.unique) {
return {
validator: (rule: any, value: any, cb: any) => {
if (!isNil(value) && value !== "") {
const valueList = formValue?.map((row) => row[name]);
const matchList = valueList?.filter(
(v, i) => isEqual(v, value) && i !== rowIndex
);
matchList?.length && cb(rule.message);
}
cb();
},
message: rule.message,
};
}
return rule;
}),
[column.rules, formValue, name, rowIndex, rowValue]
);
switch (column.type) {
case "input": {
const { placeholder, type, maxLength, allowClear } = column.props || {};
return (
<Form.Item
{...restField}
label={labelNode}
name={[fieldName, name]}
rules={rules}
>
<Input
style={{ width: "100%" }}
placeholder={placeholder}
disabled={disabled}
type={type}
maxLength={maxLength}
allowClear={allowClear}
/>
</Form.Item>
);
}
case "inputNumber": {
const { placeholder, min, max, step, precision } = column.props || {};
return (
<Form.Item
{...restField}
label={labelNode}
name={[fieldName, name]}
rules={rules}
>
<InputNumber
style={{ width: "100%" }}
placeholder={placeholder}
min={min}
max={max}
step={step}
precision={precision}
disabled={disabled}
/>
</Form.Item>
);
}
case "inputPassword": {
const { placeholder, visibilityToggle } = column.props || {};
return (
<Form.Item
{...restField}
label={labelNode}
name={[fieldName, name]}
rules={rules}
>
<Input.Password
style={{ width: "100%" }}
placeholder={placeholder}
disabled={disabled}
visibilityToggle={visibilityToggle}
/>
</Form.Item>
);
}
case "select": {
const {
placeholder,
allowClear,
mode,
options = [],
showSearch,
groupBy,
tokenSeparators,
maxTagCount,
popoverPositionType,
} = column.props || {};
const searchProps = showSearch
? {
showSearch: true,
filterOption: (input: string, option: any) => {
return option.label
?.toLowerCase()
.includes(input.trim().toLowerCase());
},
}
: {
showSearch: false,
};
return (
<Form.Item
{...restField}
label={labelNode}
name={[fieldName, name]}
rules={rules}
>
<Select
style={{ width: "100%" }}
placeholder={placeholder}
disabled={disabled}
allowClear={allowClear}
mode={mode}
tokenSeparators={tokenSeparators}
maxTagCount={maxTagCount}
{...(popoverPositionType === "parent"
? {
getPopupContainer: (triggerNode) => triggerNode.parentElement,
}
: {})}
{...searchProps}
>
{groupBy ? getOptsGroups(options, groupBy) : getOptions(options)}
</Select>
</Form.Item>
);
}
case "cascader": {
const {
placeholder,
allowClear,
options,
expandTrigger,
popupPlacement,
showSearch,
fieldNames,
} = column.props || {};
return (
<Form.Item
{...restField}
label={labelNode}
name={[fieldName, name]}
rules={rules}
>
<Cascader
style={{ width: "100%" }}
placeholder={placeholder}
allowClear={allowClear}
disabled={disabled}
expandTrigger={expandTrigger}
popupPlacement={popupPlacement}
options={options}
showSearch={showSearch}
fieldNames={fieldNames}
/>
</Form.Item>
);
}
default: {
return null;
}
}
}