From 5f8088dc7d25c59a0de2a703343f6b6ddccbb486 Mon Sep 17 00:00:00 2001 From: Merlin Beutlberger Date: Tue, 24 Jan 2023 13:51:57 +0100 Subject: [PATCH 1/3] [BREAKING] Schema: Restrict metadata.name for specVersion >= 3.0 As proposed in chapter 6 of RFC0012([1]), restrict the 'name' property for projects and extensions defining specification version 3.0 and later. BREAKING CHANGE: For projects and extensions defining specVersion 3.0 and later, the metadata.name property must satisfy the following conditions: * Must be at least 3 characters long * Must be no longer than 50 characters * Must contain lowercase characters only * Must contain alphanumeric characters, dash, underscore and period only - Exception: `@` and `/` are allowed at certain positions as explained below * Must start with an alphabetic character or an `@`-character * If a name starts with an `@`-character, it must contain exactly one forward-slash `/` - This is aligned with the npm concept for package scopes - e.g. `@org/lib.name` For details, please see refer to chapter 6 of RFC0012([1]). [1]: https://github.com/SAP/ui5-tooling/pull/664 --- lib/specifications/Specification.js | 5 +- .../schema/specVersion/kind/extension.json | 16 +++ .../kind/extension/project-shim.json | 69 +++++++++---- .../kind/extension/server-middleware.json | 63 ++++++++---- .../specVersion/kind/extension/task.json | 63 ++++++++---- .../schema/specVersion/kind/project.json | 28 ++++++ .../specVersion/kind/project/application.json | 2 +- .../specVersion/kind/project/library.json | 2 +- .../specVersion/kind/project/module.json | 74 ++++++++++---- .../kind/project/theme-library.json | 97 +++++++++++++------ test/lib/specifications/Specification.js | 2 +- .../kind/extension/project-shim.js | 52 ++++++++++ .../kind/extension/server-middleware.js | 59 +++++++++++ .../schema/specVersion/kind/extension/task.js | 59 +++++++++++ .../specVersion/kind/project/application.js | 47 +++++++++ .../specVersion/kind/project/library.js | 46 +++++++++ .../schema/specVersion/kind/project/module.js | 47 +++++++++ .../specVersion/kind/project/theme-library.js | 46 +++++++++ 18 files changed, 670 insertions(+), 107 deletions(-) diff --git a/lib/specifications/Specification.js b/lib/specifications/Specification.js index 60dbd969f..06f27feaa 100644 --- a/lib/specifications/Specification.js +++ b/lib/specifications/Specification.js @@ -120,7 +120,7 @@ class Specification { this._log.verbose(err.message); throw new Error( `${config.kind} ${config.metadata.name} defines unsupported Specification Version ` + - `${originalSpecVersion}. Please manually upgrade to 2.0 or higher. ` + + `${originalSpecVersion}. Please manually upgrade to 3.0 or higher. ` + `For details see https://sap.github.io/ui5-tooling/pages/Configuration/#specification-versions - ` + `An attempted migration to a supported specification version failed, ` + `likely due to unrecognized configuration. Check verbose log for details.`); @@ -249,6 +249,9 @@ class Specification { } _migrateLegacyProject(config) { + // Stick to 2.6 since 3.0 adds further restrictions (i.e. for the name) and enables + // functionality for extensions that shouldn't be enabled if the specVersion is not + // explicitly set to 3.x config.specVersion = "2.6"; // propertiesFileSourceEncoding (relevant for applications and libraries) default diff --git a/lib/validation/schema/specVersion/kind/extension.json b/lib/validation/schema/specVersion/kind/extension.json index c5c469100..d5dbf0854 100644 --- a/lib/validation/schema/specVersion/kind/extension.json +++ b/lib/validation/schema/specVersion/kind/extension.json @@ -70,6 +70,22 @@ "type": "string" } } + }, + "metadata-3.0": { + "type": "object", + "required": ["name"], + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "minLength": 3, + "maxLength": 50, + "pattern": "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$" + }, + "copyright": { + "type": "string" + } + } } } } diff --git a/lib/validation/schema/specVersion/kind/extension/project-shim.json b/lib/validation/schema/specVersion/kind/extension/project-shim.json index 4f3d9226c..415785f1d 100644 --- a/lib/validation/schema/specVersion/kind/extension/project-shim.json +++ b/lib/validation/schema/specVersion/kind/extension/project-shim.json @@ -6,14 +6,14 @@ "required": ["specVersion", "kind", "type", "metadata", "shims"], "if": { "properties": { - "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "3.0"] } + "specVersion": { "enum": ["3.0"] } } }, "then": { "additionalProperties": false, "properties": { "specVersion": { - "enum": ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "3.0"] + "enum": ["3.0"] }, "kind": { "enum": ["extension"] @@ -22,7 +22,7 @@ "enum": ["project-shim"] }, "metadata": { - "$ref": "../extension.json#/definitions/metadata" + "$ref": "../extension.json#/definitions/metadata-3.0" }, "shims": { "$ref": "#/definitions/shims" @@ -34,22 +34,53 @@ } }, "else": { - "additionalProperties": false, - "properties": { - "specVersion": { - "enum": ["2.0"] - }, - "kind": { - "enum": ["extension"] - }, - "type": { - "enum": ["project-shim"] - }, - "metadata": { - "$ref": "../extension.json#/definitions/metadata" - }, - "shims": { - "$ref": "#/definitions/shims" + "if": { + "properties": { + "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6"] } + } + }, + "then": { + "additionalProperties": false, + "properties": { + "specVersion": { + "enum": ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6"] + }, + "kind": { + "enum": ["extension"] + }, + "type": { + "enum": ["project-shim"] + }, + "metadata": { + "$ref": "../extension.json#/definitions/metadata" + }, + "shims": { + "$ref": "#/definitions/shims" + }, + "customConfiguration": { + "type": "object", + "additionalProperties": true + } + } + }, + "else": { + "additionalProperties": false, + "properties": { + "specVersion": { + "enum": ["2.0"] + }, + "kind": { + "enum": ["extension"] + }, + "type": { + "enum": ["project-shim"] + }, + "metadata": { + "$ref": "../extension.json#/definitions/metadata" + }, + "shims": { + "$ref": "#/definitions/shims" + } } } }, diff --git a/lib/validation/schema/specVersion/kind/extension/server-middleware.json b/lib/validation/schema/specVersion/kind/extension/server-middleware.json index 151c0c222..a65db5b56 100644 --- a/lib/validation/schema/specVersion/kind/extension/server-middleware.json +++ b/lib/validation/schema/specVersion/kind/extension/server-middleware.json @@ -7,13 +7,13 @@ "required": ["specVersion", "kind", "type", "metadata", "middleware"], "if": { "properties": { - "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "3.0"] } + "specVersion": { "enum": ["3.0"] } } }, "then": { "additionalProperties": false, "properties": { - "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "3.0"] }, + "specVersion": { "enum": ["3.0"] }, "kind": { "enum": ["extension"] }, @@ -21,7 +21,7 @@ "enum": ["server-middleware"] }, "metadata": { - "$ref": "../extension.json#/definitions/metadata" + "$ref": "../extension.json#/definitions/metadata-3.0" }, "middleware": { "$ref": "#/definitions/middleware" @@ -33,20 +33,49 @@ } }, "else": { - "additionalProperties": false, - "properties": { - "specVersion": { "enum": ["2.0"] }, - "kind": { - "enum": ["extension"] - }, - "type": { - "enum": ["server-middleware"] - }, - "metadata": { - "$ref": "../extension.json#/definitions/metadata" - }, - "middleware": { - "$ref": "#/definitions/middleware" + "if": { + "properties": { + "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6"] } + } + }, + "then": { + "additionalProperties": false, + "properties": { + "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6"] }, + "kind": { + "enum": ["extension"] + }, + "type": { + "enum": ["server-middleware"] + }, + "metadata": { + "$ref": "../extension.json#/definitions/metadata" + }, + "middleware": { + "$ref": "#/definitions/middleware" + }, + "customConfiguration": { + "type": "object", + "additionalProperties": true + } + } + }, + "else": { + "additionalProperties": false, + "properties": { + "specVersion": { "enum": ["2.0"] }, + "kind": { + "enum": ["extension"] + }, + "type": { + "enum": ["server-middleware"] + }, + "metadata": { + "$ref": "../extension.json#/definitions/metadata" + }, + "middleware": { + "$ref": "#/definitions/middleware" + } } } }, diff --git a/lib/validation/schema/specVersion/kind/extension/task.json b/lib/validation/schema/specVersion/kind/extension/task.json index ab5413c78..f19291e0c 100644 --- a/lib/validation/schema/specVersion/kind/extension/task.json +++ b/lib/validation/schema/specVersion/kind/extension/task.json @@ -6,13 +6,13 @@ "required": ["specVersion", "kind", "type", "metadata", "task"], "if": { "properties": { - "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "3.0"] } + "specVersion": { "enum": ["3.0"] } } }, "then": { "additionalProperties": false, "properties": { - "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "3.0"] }, + "specVersion": { "enum": ["3.0"] }, "kind": { "enum": ["extension"] }, @@ -20,7 +20,7 @@ "enum": ["task"] }, "metadata": { - "$ref": "../extension.json#/definitions/metadata" + "$ref": "../extension.json#/definitions/metadata-3.0" }, "task": { "$ref": "#/definitions/task" @@ -32,20 +32,49 @@ } }, "else": { - "additionalProperties": false, - "properties": { - "specVersion": { "enum": ["2.0"] }, - "kind": { - "enum": ["extension"] - }, - "type": { - "enum": ["task"] - }, - "metadata": { - "$ref": "../extension.json#/definitions/metadata" - }, - "task": { - "$ref": "#/definitions/task" + "if": { + "properties": { + "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6"] } + } + }, + "then": { + "additionalProperties": false, + "properties": { + "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6"] }, + "kind": { + "enum": ["extension"] + }, + "type": { + "enum": ["task"] + }, + "metadata": { + "$ref": "../extension.json#/definitions/metadata" + }, + "task": { + "$ref": "#/definitions/task" + }, + "customConfiguration": { + "type": "object", + "additionalProperties": true + } + } + }, + "else": { + "additionalProperties": false, + "properties": { + "specVersion": { "enum": ["2.0"] }, + "kind": { + "enum": ["extension"] + }, + "type": { + "enum": ["task"] + }, + "metadata": { + "$ref": "../extension.json#/definitions/metadata" + }, + "task": { + "$ref": "#/definitions/task" + } } } }, diff --git a/lib/validation/schema/specVersion/kind/project.json b/lib/validation/schema/specVersion/kind/project.json index 3d6a1a49b..acdec24e8 100644 --- a/lib/validation/schema/specVersion/kind/project.json +++ b/lib/validation/schema/specVersion/kind/project.json @@ -93,6 +93,34 @@ } } }, + "metadata-3.0": { + "type": "object", + "required": ["name"], + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "minLength": 3, + "maxLength": 50, + "pattern": "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$" + }, + "copyright": { + "type": "string" + }, + "deprecated": { + "type": "boolean", + "default": false + }, + "sapInternal": { + "type": "boolean", + "default": false + }, + "allowSapInternal": { + "type": "boolean", + "default": false + } + } + }, "resources-configuration-propertiesFileSourceEncoding": { "enum": ["UTF-8", "ISO-8859-1"], "default": "UTF-8", diff --git a/lib/validation/schema/specVersion/kind/project/application.json b/lib/validation/schema/specVersion/kind/project/application.json index fd0b063c2..81073634a 100644 --- a/lib/validation/schema/specVersion/kind/project/application.json +++ b/lib/validation/schema/specVersion/kind/project/application.json @@ -20,7 +20,7 @@ "enum": ["application"] }, "metadata": { - "$ref": "../project.json#/definitions/metadata" + "$ref": "../project.json#/definitions/metadata-3.0" }, "framework": { "$ref": "../project.json#/definitions/framework" diff --git a/lib/validation/schema/specVersion/kind/project/library.json b/lib/validation/schema/specVersion/kind/project/library.json index 86f1efe0a..d36a1f83e 100644 --- a/lib/validation/schema/specVersion/kind/project/library.json +++ b/lib/validation/schema/specVersion/kind/project/library.json @@ -20,7 +20,7 @@ "enum": ["library"] }, "metadata": { - "$ref": "../project.json#/definitions/metadata" + "$ref": "../project.json#/definitions/metadata-3.0" }, "framework": { "$ref": "../project.json#/definitions/framework" diff --git a/lib/validation/schema/specVersion/kind/project/module.json b/lib/validation/schema/specVersion/kind/project/module.json index 8bd717ff5..9684f27d1 100644 --- a/lib/validation/schema/specVersion/kind/project/module.json +++ b/lib/validation/schema/specVersion/kind/project/module.json @@ -6,13 +6,13 @@ "required": ["specVersion", "type", "metadata"], "if": { "properties": { - "specVersion": { "enum": ["2.5", "2.6", "3.0"] } + "specVersion": { "enum": ["3.0"] } } }, "then": { "additionalProperties": false, "properties": { - "specVersion": { "enum": ["2.5", "2.6", "3.0"] }, + "specVersion": { "enum": ["3.0"] }, "kind": { "enum": ["project", null] }, @@ -20,7 +20,7 @@ "enum": ["module"] }, "metadata": { - "$ref": "../project.json#/definitions/metadata" + "$ref": "../project.json#/definitions/metadata-3.0" }, "resources": { "$ref": "#/definitions/resources" @@ -40,13 +40,13 @@ "else": { "if": { "properties": { - "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4"] } + "specVersion": { "enum": ["2.5", "2.6"] } } }, "then": { "additionalProperties": false, "properties": { - "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4"] }, + "specVersion": { "enum": ["2.5", "2.6"] }, "kind": { "enum": ["project", null] }, @@ -59,6 +59,12 @@ "resources": { "$ref": "#/definitions/resources" }, + "builder": { + "$ref": "#/definitions/builder-specVersion-2.5" + }, + "server": { + "$ref": "../project.json#/definitions/server" + }, "customConfiguration": { "type": "object", "additionalProperties": true @@ -66,25 +72,53 @@ } }, "else": { - "additionalProperties": false, - "properties": { - "specVersion": { "enum": ["2.0"] }, - "kind": { - "enum": ["project", null] - }, - "type": { - "enum": ["module"] - }, - "metadata": { - "$ref": "../project.json#/definitions/metadata" - }, - "resources": { - "$ref": "#/definitions/resources" + "if": { + "properties": { + "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4"] } + } + }, + "then": { + "additionalProperties": false, + "properties": { + "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4"] }, + "kind": { + "enum": ["project", null] + }, + "type": { + "enum": ["module"] + }, + "metadata": { + "$ref": "../project.json#/definitions/metadata" + }, + "resources": { + "$ref": "#/definitions/resources" + }, + "customConfiguration": { + "type": "object", + "additionalProperties": true + } + } + }, + "else": { + "additionalProperties": false, + "properties": { + "specVersion": { "enum": ["2.0"] }, + "kind": { + "enum": ["project", null] + }, + "type": { + "enum": ["module"] + }, + "metadata": { + "$ref": "../project.json#/definitions/metadata" + }, + "resources": { + "$ref": "#/definitions/resources" + } } } } }, - "definitions": { "resources": { "type": "object", diff --git a/lib/validation/schema/specVersion/kind/project/theme-library.json b/lib/validation/schema/specVersion/kind/project/theme-library.json index fc292179a..522b7064a 100644 --- a/lib/validation/schema/specVersion/kind/project/theme-library.json +++ b/lib/validation/schema/specVersion/kind/project/theme-library.json @@ -6,13 +6,13 @@ "required": ["specVersion", "type", "metadata"], "if": { "properties": { - "specVersion": { "enum": ["2.5", "2.6", "3.0"] } + "specVersion": { "enum": ["3.0"] } } }, "then": { "additionalProperties": false, "properties": { - "specVersion": { "enum": ["2.5", "2.6", "3.0"] }, + "specVersion": { "enum": ["3.0"] }, "kind": { "enum": ["project", null] }, @@ -20,7 +20,7 @@ "enum": ["theme-library"] }, "metadata": { - "$ref": "../project.json#/definitions/metadata" + "$ref": "../project.json#/definitions/metadata-3.0" }, "framework": { "$ref": "../project.json#/definitions/framework" @@ -43,13 +43,13 @@ "else": { "if": { "properties": { - "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4"] } + "specVersion": { "enum": ["2.5", "2.6"] } } }, "then": { "additionalProperties": false, "properties": { - "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4"] }, + "specVersion": { "enum": ["2.5", "2.6"] }, "kind": { "enum": ["project", null] }, @@ -66,7 +66,7 @@ "$ref": "library.json#/definitions/resources" }, "builder": { - "$ref": "#/definitions/builder" + "$ref": "#/definitions/builder-specVersion-2.5" }, "server": { "$ref": "../project.json#/definitions/server" @@ -78,34 +78,71 @@ } }, "else": { - "additionalProperties": false, - "properties": { - "specVersion": { "enum": ["2.0"] }, - "kind": { - "enum": ["project", null] - }, - "type": { - "enum": ["theme-library"] - }, - "metadata": { - "$ref": "../project.json#/definitions/metadata" - }, - "framework": { - "$ref": "../project.json#/definitions/framework" - }, - "resources": { - "$ref": "library.json#/definitions/resources" - }, - "builder": { - "$ref": "#/definitions/builder" - }, - "server": { - "$ref": "../project.json#/definitions/server" + "if": { + "properties": { + "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4"] } + } + }, + "then": { + "additionalProperties": false, + "properties": { + "specVersion": { "enum": ["2.1", "2.2", "2.3", "2.4"] }, + "kind": { + "enum": ["project", null] + }, + "type": { + "enum": ["theme-library"] + }, + "metadata": { + "$ref": "../project.json#/definitions/metadata" + }, + "framework": { + "$ref": "../project.json#/definitions/framework" + }, + "resources": { + "$ref": "library.json#/definitions/resources" + }, + "builder": { + "$ref": "#/definitions/builder" + }, + "server": { + "$ref": "../project.json#/definitions/server" + }, + "customConfiguration": { + "type": "object", + "additionalProperties": true + } + } + }, + "else": { + "additionalProperties": false, + "properties": { + "specVersion": { "enum": ["2.0"] }, + "kind": { + "enum": ["project", null] + }, + "type": { + "enum": ["theme-library"] + }, + "metadata": { + "$ref": "../project.json#/definitions/metadata" + }, + "framework": { + "$ref": "../project.json#/definitions/framework" + }, + "resources": { + "$ref": "library.json#/definitions/resources" + }, + "builder": { + "$ref": "#/definitions/builder" + }, + "server": { + "$ref": "../project.json#/definitions/server" + } } } } }, - "definitions": { "builder": { "type": "object", diff --git a/test/lib/specifications/Specification.js b/test/lib/specifications/Specification.js index 6fbafbe74..aee440410 100644 --- a/test/lib/specifications/Specification.js +++ b/test/lib/specifications/Specification.js @@ -149,7 +149,7 @@ test("Migrate legacy project unexpected configuration", async (t) => { const err = await t.throwsAsync(Specification.create(t.context.basicProjectInput)); t.is(err.message, - "project application.a defines unsupported Specification Version 1.0. Please manually upgrade to 2.0 or " + + "project application.a defines unsupported Specification Version 1.0. Please manually upgrade to 3.0 or " + "higher. For details see https://sap.github.io/ui5-tooling/pages/Configuration/#specification-versions - " + "An attempted migration to a supported specification version failed, likely due to unrecognized " + "configuration. Check verbose log for details.", diff --git a/test/lib/validation/schema/specVersion/kind/extension/project-shim.js b/test/lib/validation/schema/specVersion/kind/extension/project-shim.js index 3fb2fb286..1c4438f83 100644 --- a/test/lib/validation/schema/specVersion/kind/extension/project-shim.js +++ b/test/lib/validation/schema/specVersion/kind/extension/project-shim.js @@ -122,6 +122,58 @@ test.after.always((t) => { }); }); +["3.0"].forEach(function(specVersion) { + test(`Invalid project name (specVersion ${specVersion})`, async (t) => { + await assertValidation(t, { + "specVersion": specVersion, + "kind": "extension", + "type": "project-shim", + "metadata": { + "name": "illegal-๐Ÿฆœ" + }, + "shims": {} + }, [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "kind": "extension", + "type": "project-shim", + "metadata": { + "name": "a" + }, + "shims": {} + }, [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: `should NOT be shorter than 3 characters`, + params: { + limit: 3, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "kind": "extension", + "type": "project-shim", + "metadata": { + "name": "a".repeat(51) + }, + "shims": {} + }, [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: `should NOT be longer than 50 characters`, + params: { + limit: 50, + }, + }]); + }); +}); const additionalConfiguration = { "shims": { diff --git a/test/lib/validation/schema/specVersion/kind/extension/server-middleware.js b/test/lib/validation/schema/specVersion/kind/extension/server-middleware.js index 6a97ac218..6ab2e26cd 100644 --- a/test/lib/validation/schema/specVersion/kind/extension/server-middleware.js +++ b/test/lib/validation/schema/specVersion/kind/extension/server-middleware.js @@ -40,6 +40,65 @@ test.after.always((t) => { t.context.ajvCoverage.verify(thresholds); }); +["3.0"].forEach(function(specVersion) { + test(`Invalid project name (specVersion ${specVersion})`, async (t) => { + await assertValidation(t, { + "specVersion": specVersion, + "kind": "extension", + "type": "server-middleware", + "metadata": { + "name": "illegal-๐Ÿฆœ" + }, + "middleware": { + "path": "/bar" + } + }, [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "kind": "extension", + "type": "server-middleware", + "metadata": { + "name": "a" + }, + "middleware": { + "path": "/bar" + } + }, [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: `should NOT be shorter than 3 characters`, + params: { + limit: 3, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "kind": "extension", + "type": "server-middleware", + "metadata": { + "name": "a".repeat(51) + }, + "middleware": { + "path": "/bar" + } + }, [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: `should NOT be longer than 50 characters`, + params: { + limit: 50, + }, + }]); + }); +}); + const additionalConfiguration = { "middleware": { "path": "/foo" diff --git a/test/lib/validation/schema/specVersion/kind/extension/task.js b/test/lib/validation/schema/specVersion/kind/extension/task.js index 7abbf36d0..d0aef0bdb 100644 --- a/test/lib/validation/schema/specVersion/kind/extension/task.js +++ b/test/lib/validation/schema/specVersion/kind/extension/task.js @@ -40,6 +40,65 @@ test.after.always((t) => { t.context.ajvCoverage.verify(thresholds); }); +["3.0"].forEach(function(specVersion) { + test(`Invalid project name (specVersion ${specVersion})`, async (t) => { + await assertValidation(t, { + "specVersion": specVersion, + "kind": "extension", + "type": "task", + "metadata": { + "name": "illegal-๐Ÿฆœ" + }, + "task": { + "path": "/bar" + } + }, [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "kind": "extension", + "type": "task", + "metadata": { + "name": "a" + }, + "task": { + "path": "/bar" + } + }, [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: `should NOT be shorter than 3 characters`, + params: { + limit: 3, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "kind": "extension", + "type": "task", + "metadata": { + "name": "a".repeat(51) + }, + "task": { + "path": "/bar" + } + }, [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: `should NOT be longer than 50 characters`, + params: { + limit: 50, + }, + }]); + }); +}); + const additionalConfiguration = { "task": { "path": "/foo" diff --git a/test/lib/validation/schema/specVersion/kind/project/application.js b/test/lib/validation/schema/specVersion/kind/project/application.js index 81b959e4f..2726c42a3 100644 --- a/test/lib/validation/schema/specVersion/kind/project/application.js +++ b/test/lib/validation/schema/specVersion/kind/project/application.js @@ -942,4 +942,51 @@ test.after.always((t) => { }); }); +["3.0"].forEach(function(specVersion) { + test(`Invalid project name (specVersion ${specVersion})`, async (t) => { + await assertValidation(t, { + "specVersion": specVersion, + "type": "application", + "metadata": { + "name": "illegal-๐Ÿฆœ" + } + }, [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "type": "application", + "metadata": { + "name": "a" + } + }, [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: `should NOT be shorter than 3 characters`, + params: { + limit: 3, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "type": "application", + "metadata": { + "name": "a".repeat(51) + } + }, [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: `should NOT be longer than 50 characters`, + params: { + limit: 50, + }, + }]); + }); +}); + project.defineTests(test, assertValidation, "application"); diff --git a/test/lib/validation/schema/specVersion/kind/project/library.js b/test/lib/validation/schema/specVersion/kind/project/library.js index 3ba3ecfd6..d8917ab33 100644 --- a/test/lib/validation/schema/specVersion/kind/project/library.js +++ b/test/lib/validation/schema/specVersion/kind/project/library.js @@ -1115,4 +1115,50 @@ test.after.always((t) => { }); }); +["3.0"].forEach(function(specVersion) { + test(`Invalid project name (specVersion ${specVersion})`, async (t) => { + await assertValidation(t, { + "specVersion": specVersion, + "type": "library", + "metadata": { + "name": "illegal-๐Ÿฆœ" + } + }, [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "type": "library", + "metadata": { + "name": "a" + } + }, [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: `should NOT be shorter than 3 characters`, + params: { + limit: 3, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "type": "library", + "metadata": { + "name": "a".repeat(51) + } + }, [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: `should NOT be longer than 50 characters`, + params: { + limit: 50, + }, + }]); + }); +}); project.defineTests(test, assertValidation, "library"); diff --git a/test/lib/validation/schema/specVersion/kind/project/module.js b/test/lib/validation/schema/specVersion/kind/project/module.js index a750806b4..e24ac1f13 100644 --- a/test/lib/validation/schema/specVersion/kind/project/module.js +++ b/test/lib/validation/schema/specVersion/kind/project/module.js @@ -344,4 +344,51 @@ test.after.always((t) => { }); }); +["3.0"].forEach(function(specVersion) { + test(`Invalid project name (specVersion ${specVersion})`, async (t) => { + await assertValidation(t, { + "specVersion": specVersion, + "type": "module", + "metadata": { + "name": "illegal-๐Ÿฆœ" + } + }, [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "type": "module", + "metadata": { + "name": "a" + } + }, [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: `should NOT be shorter than 3 characters`, + params: { + limit: 3, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "type": "module", + "metadata": { + "name": "a".repeat(51) + } + }, [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: `should NOT be longer than 50 characters`, + params: { + limit: 50, + }, + }]); + }); +}); + project.defineTests(test, assertValidation, "module"); diff --git a/test/lib/validation/schema/specVersion/kind/project/theme-library.js b/test/lib/validation/schema/specVersion/kind/project/theme-library.js index 24abd992c..faca87799 100644 --- a/test/lib/validation/schema/specVersion/kind/project/theme-library.js +++ b/test/lib/validation/schema/specVersion/kind/project/theme-library.js @@ -348,4 +348,50 @@ test.after.always((t) => { }); }); +["3.0"].forEach(function(specVersion) { + test(`Invalid project name (specVersion ${specVersion})`, async (t) => { + await assertValidation(t, { + "specVersion": specVersion, + "type": "theme-library", + "metadata": { + "name": "illegal-๐Ÿฆœ" + } + }, [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "type": "theme-library", + "metadata": { + "name": "a" + } + }, [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: `should NOT be shorter than 3 characters`, + params: { + limit: 3, + }, + }]); + await assertValidation(t, { + "specVersion": specVersion, + "type": "theme-library", + "metadata": { + "name": "a".repeat(51) + } + }, [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: `should NOT be longer than 50 characters`, + params: { + limit: 50, + }, + }]); + }); +}); project.defineTests(test, assertValidation, "theme-library"); From d5484f6e9d0a7c3b21a2b336f007f3d28b9b4f52 Mon Sep 17 00:00:00 2001 From: Merlin Beutlberger Date: Tue, 24 Jan 2023 18:18:53 +0100 Subject: [PATCH 2/3] [INTERNAL] Schema: Add metadata.name tests for legacy specVersion Specification Versions <3.0 should allow any names --- .../schema/specVersion/kind/extension.js | 40 +++++++++++++++++++ .../schema/specVersion/kind/project.js | 40 +++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/test/lib/validation/schema/specVersion/kind/extension.js b/test/lib/validation/schema/specVersion/kind/extension.js index 565b92245..817e6c31b 100644 --- a/test/lib/validation/schema/specVersion/kind/extension.js +++ b/test/lib/validation/schema/specVersion/kind/extension.js @@ -152,3 +152,43 @@ test.after.always((t) => { }]); }); }); + +test("Legacy: Special characters in name (task)", async (t) => { + await assertValidation(t, { + "specVersion": "2.0", + "kind": "extension", + "type": "task", + "metadata": { + "name": "รค".repeat(51) + }, + "task": { + "path": "task.js" + } + }); +}); + +test("Legacy: Special characters in name (server-middleware)", async (t) => { + await assertValidation(t, { + "specVersion": "2.0", + "kind": "extension", + "type": "server-middleware", + "metadata": { + "name": "@my(middleware)" + }, + "middleware": { + "path": "middleware.js" + } + }); +}); + +test("Legacy: Special characters in name (project-shim)", async (t) => { + await assertValidation(t, { + "specVersion": "2.0", + "kind": "extension", + "type": "project-shim", + "metadata": { + "name": "my/(project)-shim" + }, + "shims": {} + }); +}); diff --git a/test/lib/validation/schema/specVersion/kind/project.js b/test/lib/validation/schema/specVersion/kind/project.js index 231c0ef29..2c9c2290a 100644 --- a/test/lib/validation/schema/specVersion/kind/project.js +++ b/test/lib/validation/schema/specVersion/kind/project.js @@ -195,3 +195,43 @@ test("No specVersion", async (t) => { } }]); }); + +test("Legacy: Special characters in name (application)", async (t) => { + await assertValidation(t, { + "specVersion": "2.0", + "type": "application", + "metadata": { + "name": "/".repeat(51) + } + }); +}); + +test("Legacy: Special characters in name (library)", async (t) => { + await assertValidation(t, { + "specVersion": "2.0", + "type": "library", + "metadata": { + "name": "my/(library)" + } + }); +}); + +test("Legacy: Special characters in name (theme-library)", async (t) => { + await assertValidation(t, { + "specVersion": "2.0", + "type": "theme-library", + "metadata": { + "name": "my/(theme)-library" + } + }); +}); + +test("Legacy: Special characters in name (module)", async (t) => { + await assertValidation(t, { + "specVersion": "2.0", + "type": "module", + "metadata": { + "name": "my/(module)" + } + }); +}); From 45f2871b193203902fa6318fbff71f69ce348083 Mon Sep 17 00:00:00 2001 From: Merlin Beutlberger Date: Wed, 25 Jan 2023 11:45:01 +0100 Subject: [PATCH 3/3] [INTERNAL] Schema: Add error message for metadata.name Also escape forward slash just to be sure --- .../schema/specVersion/kind/extension.json | 5 +- .../schema/specVersion/kind/project.json | 5 +- .../validation/schema/__helper__/extension.js | 54 ++++++++++++++- .../validation/schema/__helper__/project.js | 68 +++++++++++++------ .../kind/extension/project-shim.js | 48 ++++++++++--- .../kind/extension/server-middleware.js | 46 ++++++++++--- .../schema/specVersion/kind/extension/task.js | 46 ++++++++++--- .../specVersion/kind/project/application.js | 41 ++++++++--- .../specVersion/kind/project/library.js | 39 ++++++++--- .../schema/specVersion/kind/project/module.js | 44 +++++++++--- .../specVersion/kind/project/theme-library.js | 39 ++++++++--- 11 files changed, 345 insertions(+), 90 deletions(-) diff --git a/lib/validation/schema/specVersion/kind/extension.json b/lib/validation/schema/specVersion/kind/extension.json index d5dbf0854..2c673c508 100644 --- a/lib/validation/schema/specVersion/kind/extension.json +++ b/lib/validation/schema/specVersion/kind/extension.json @@ -80,7 +80,10 @@ "type": "string", "minLength": 3, "maxLength": 50, - "pattern": "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$" + "pattern": "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$", + "title": "Extension Name", + "description": "Unique identifier for the extension. E.g. ui5-task-fearless-rock", + "errorMessage": "Not a valid extension name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name" }, "copyright": { "type": "string" diff --git a/lib/validation/schema/specVersion/kind/project.json b/lib/validation/schema/specVersion/kind/project.json index acdec24e8..3d8554584 100644 --- a/lib/validation/schema/specVersion/kind/project.json +++ b/lib/validation/schema/specVersion/kind/project.json @@ -102,7 +102,10 @@ "type": "string", "minLength": 3, "maxLength": 50, - "pattern": "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$" + "pattern": "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$", + "title": "Project Name", + "description": "Unique identifier for the project. E.g. organization.product.project", + "errorMessage": "Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name" }, "copyright": { "type": "string" diff --git a/test/lib/validation/schema/__helper__/extension.js b/test/lib/validation/schema/__helper__/extension.js index 33143db77..79799ee96 100644 --- a/test/lib/validation/schema/__helper__/extension.js +++ b/test/lib/validation/schema/__helper__/extension.js @@ -18,7 +18,7 @@ export default { customConfiguration.defineTests(test, assertValidation, type, additionalConfiguration); - ["2.6", "2.5", "2.4", "2.3", "2.2", "2.1", "2.0"].forEach((specVersion) => { + ["3.0", "2.6", "2.5", "2.4", "2.3", "2.2", "2.1", "2.0"].forEach((specVersion) => { test(`kind: extension / type: ${type} basic (${specVersion})`, async (t) => { await assertValidation(t, Object.assign({ "specVersion": specVersion, @@ -66,5 +66,57 @@ export default { }]); }); }); + + ["2.6", "2.5", "2.4", "2.3", "2.2", "2.1", "2.0"].forEach((specVersion) => { + test(`kind: extension / type: ${type}: Invalid metadata.name (${specVersion})`, async (t) => { + await assertValidation(t, Object.assign({ + "specVersion": specVersion, + "type": type, + "metadata": { + "name": {} + } + }, additionalConfiguration), [{ + dataPath: "/metadata/name", + keyword: "type", + message: "should be string", + params: { + type: "string" + } + }]); + }); + }); + + ["3.0"].forEach((specVersion) => { + test(`kind: extension / type: ${type}: Invalid metadata.name (${specVersion})`, async (t) => { + await assertValidation(t, Object.assign({ + "specVersion": specVersion, + "type": type, + "metadata": { + "name": {} + } + }, additionalConfiguration), [{ + dataPath: "/metadata/name", + keyword: "type", + message: "should be string", + params: { + type: "string", + }, + }, { + dataPath: "/metadata/name", + keyword: "errorMessage", + message: `Not a valid extension name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, + params: { + errors: [{ + dataPath: "/metadata/name", + keyword: "type", + message: "should be string", + params: { + type: "string", + } + }] + }, + }]); + }); + }); } }; diff --git a/test/lib/validation/schema/__helper__/project.js b/test/lib/validation/schema/__helper__/project.js index 777aeba51..50737b761 100644 --- a/test/lib/validation/schema/__helper__/project.js +++ b/test/lib/validation/schema/__helper__/project.js @@ -75,25 +75,6 @@ export default { }]); }); - test(`${type} (specVersion ${specVersion}): Invalid metadata.name`, async (t) => { - await assertValidation(t, { - "specVersion": specVersion, - "type": type, - "metadata": { - "name": {} - } - }, [ - { - dataPath: "/metadata/name", - keyword: "type", - message: "should be string", - params: { - type: "string" - } - } - ]); - }); - test(`${type} (specVersion ${specVersion}): Invalid metadata.copyright`, async (t) => { await assertValidation(t, { "specVersion": specVersion, @@ -278,5 +259,54 @@ export default { }]); }); }); + + ["2.6", "2.5", "2.4", "2.3", "2.2", "2.1", "2.0"].forEach((specVersion) => { + test(`${type} (specVersion ${specVersion}): Invalid metadata.name`, async (t) => { + await assertValidation(t, { + "specVersion": specVersion, + "type": type, + "metadata": { + "name": {} + } + }, [ + { + dataPath: "/metadata/name", + keyword: "type", + message: "should be string", + params: { + type: "string" + } + } + ]); + }); + }); + + ["3.0"].forEach((specVersion) => { + test(`${type} (specVersion ${specVersion}): Invalid metadata.name`, async (t) => { + await assertValidation(t, { + "specVersion": specVersion, + "type": type, + "metadata": { + "name": {} + } + }, [ + { + dataPath: "/metadata/name", + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, + params: { + errors: [{ + dataPath: "/metadata/name", + keyword: "type", + message: "should be string", + params: { + type: "string", + } + }] + }, + } + ]); + }); + }); } }; diff --git a/test/lib/validation/schema/specVersion/kind/extension/project-shim.js b/test/lib/validation/schema/specVersion/kind/extension/project-shim.js index 1c4438f83..b2583a12b 100644 --- a/test/lib/validation/schema/specVersion/kind/extension/project-shim.js +++ b/test/lib/validation/schema/specVersion/kind/extension/project-shim.js @@ -15,6 +15,11 @@ async function assertValidation(t, config, expectedErrors = undefined) { }); validationError.errors.forEach((error) => { delete error.schemaPath; + if (error.params && Array.isArray(error.params.errors)) { + error.params.errors.forEach(($) => { + delete $.schemaPath; + }); + } }); t.deepEqual(validationError.errors, expectedErrors); } else { @@ -123,21 +128,28 @@ test.after.always((t) => { }); ["3.0"].forEach(function(specVersion) { - test(`Invalid project name (specVersion ${specVersion})`, async (t) => { + test(`Invalid extension name (specVersion ${specVersion})`, async (t) => { await assertValidation(t, { "specVersion": specVersion, "kind": "extension", "type": "project-shim", "metadata": { - "name": "illegal-๐Ÿฆœ" + "name": "illegal/name" }, "shims": {} }, [{ dataPath: "/metadata/name", - keyword: "pattern", - message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + keyword: "errorMessage", + message: `Not a valid extension name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + errors: [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$", + } + }] }, }]); await assertValidation(t, { @@ -150,10 +162,17 @@ test.after.always((t) => { "shims": {} }, [{ dataPath: "/metadata/name", - keyword: "minLength", - message: `should NOT be shorter than 3 characters`, + keyword: "errorMessage", + message: `Not a valid extension name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 3, + errors: [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: "should NOT be shorter than 3 characters", + params: { + limit: 3, + } + }] }, }]); await assertValidation(t, { @@ -166,10 +185,17 @@ test.after.always((t) => { "shims": {} }, [{ dataPath: "/metadata/name", - keyword: "maxLength", - message: `should NOT be longer than 50 characters`, + keyword: "errorMessage", + message: `Not a valid extension name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 50, + errors: [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: "should NOT be longer than 50 characters", + params: { + limit: 50, + } + }] }, }]); }); diff --git a/test/lib/validation/schema/specVersion/kind/extension/server-middleware.js b/test/lib/validation/schema/specVersion/kind/extension/server-middleware.js index 6ab2e26cd..54dab5cbd 100644 --- a/test/lib/validation/schema/specVersion/kind/extension/server-middleware.js +++ b/test/lib/validation/schema/specVersion/kind/extension/server-middleware.js @@ -15,6 +15,11 @@ async function assertValidation(t, config, expectedErrors = undefined) { }); validationError.errors.forEach((error) => { delete error.schemaPath; + if (error.params && Array.isArray(error.params.errors)) { + error.params.errors.forEach(($) => { + delete $.schemaPath; + }); + } }); t.deepEqual(validationError.errors, expectedErrors); } else { @@ -41,7 +46,7 @@ test.after.always((t) => { }); ["3.0"].forEach(function(specVersion) { - test(`Invalid project name (specVersion ${specVersion})`, async (t) => { + test(`Invalid extension name (specVersion ${specVersion})`, async (t) => { await assertValidation(t, { "specVersion": specVersion, "kind": "extension", @@ -54,10 +59,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "pattern", - message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + keyword: "errorMessage", + message: `Not a valid extension name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + errors: [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$", + } + }] }, }]); await assertValidation(t, { @@ -72,10 +84,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "minLength", - message: `should NOT be shorter than 3 characters`, + keyword: "errorMessage", + message: `Not a valid extension name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 3, + errors: [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: "should NOT be shorter than 3 characters", + params: { + limit: 3, + } + }] }, }]); await assertValidation(t, { @@ -90,10 +109,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "maxLength", - message: `should NOT be longer than 50 characters`, + keyword: "errorMessage", + message: `Not a valid extension name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 50, + errors: [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: "should NOT be longer than 50 characters", + params: { + limit: 50, + } + }] }, }]); }); diff --git a/test/lib/validation/schema/specVersion/kind/extension/task.js b/test/lib/validation/schema/specVersion/kind/extension/task.js index d0aef0bdb..63f5be3e9 100644 --- a/test/lib/validation/schema/specVersion/kind/extension/task.js +++ b/test/lib/validation/schema/specVersion/kind/extension/task.js @@ -15,6 +15,11 @@ async function assertValidation(t, config, expectedErrors = undefined) { }); validationError.errors.forEach((error) => { delete error.schemaPath; + if (error.params && Array.isArray(error.params.errors)) { + error.params.errors.forEach(($) => { + delete $.schemaPath; + }); + } }); t.deepEqual(validationError.errors, expectedErrors); } else { @@ -41,7 +46,7 @@ test.after.always((t) => { }); ["3.0"].forEach(function(specVersion) { - test(`Invalid project name (specVersion ${specVersion})`, async (t) => { + test(`Invalid extension name (specVersion ${specVersion})`, async (t) => { await assertValidation(t, { "specVersion": specVersion, "kind": "extension", @@ -54,10 +59,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "pattern", - message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + keyword: "errorMessage", + message: `Not a valid extension name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + errors: [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$", + } + }] }, }]); await assertValidation(t, { @@ -72,10 +84,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "minLength", - message: `should NOT be shorter than 3 characters`, + keyword: "errorMessage", + message: `Not a valid extension name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 3, + errors: [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: "should NOT be shorter than 3 characters", + params: { + limit: 3, + } + }] }, }]); await assertValidation(t, { @@ -90,10 +109,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "maxLength", - message: `should NOT be longer than 50 characters`, + keyword: "errorMessage", + message: `Not a valid extension name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 50, + errors: [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: "should NOT be longer than 50 characters", + params: { + limit: 50, + } + }] }, }]); }); diff --git a/test/lib/validation/schema/specVersion/kind/project/application.js b/test/lib/validation/schema/specVersion/kind/project/application.js index 2726c42a3..4c0a73d5f 100644 --- a/test/lib/validation/schema/specVersion/kind/project/application.js +++ b/test/lib/validation/schema/specVersion/kind/project/application.js @@ -948,14 +948,21 @@ test.after.always((t) => { "specVersion": specVersion, "type": "application", "metadata": { - "name": "illegal-๐Ÿฆœ" + "name": "illegal/name" } }, [{ dataPath: "/metadata/name", - keyword: "pattern", - message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + errors: [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$", + }, + }] }, }]); await assertValidation(t, { @@ -966,10 +973,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "minLength", - message: `should NOT be shorter than 3 characters`, + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 3, + errors: [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: "should NOT be shorter than 3 characters", + params: { + limit: 3, + }, + }] }, }]); await assertValidation(t, { @@ -980,10 +994,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "maxLength", - message: `should NOT be longer than 50 characters`, + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 50, + errors: [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: "should NOT be longer than 50 characters", + params: { + limit: 50, + }, + }] }, }]); }); diff --git a/test/lib/validation/schema/specVersion/kind/project/library.js b/test/lib/validation/schema/specVersion/kind/project/library.js index d8917ab33..60e0c6225 100644 --- a/test/lib/validation/schema/specVersion/kind/project/library.js +++ b/test/lib/validation/schema/specVersion/kind/project/library.js @@ -1125,10 +1125,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "pattern", - message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + errors: [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$", + }, + }] }, }]); await assertValidation(t, { @@ -1139,10 +1146,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "minLength", - message: `should NOT be shorter than 3 characters`, + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 3, + errors: [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: "should NOT be shorter than 3 characters", + params: { + limit: 3, + }, + }] }, }]); await assertValidation(t, { @@ -1153,10 +1167,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "maxLength", - message: `should NOT be longer than 50 characters`, + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 50, + errors: [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: "should NOT be longer than 50 characters", + params: { + limit: 50, + }, + }] }, }]); }); diff --git a/test/lib/validation/schema/specVersion/kind/project/module.js b/test/lib/validation/schema/specVersion/kind/project/module.js index e24ac1f13..06e059cf7 100644 --- a/test/lib/validation/schema/specVersion/kind/project/module.js +++ b/test/lib/validation/schema/specVersion/kind/project/module.js @@ -15,6 +15,11 @@ async function assertValidation(t, config, expectedErrors = undefined) { }); validationError.errors.forEach((error) => { delete error.schemaPath; + if (error.params && Array.isArray(error.params.errors)) { + error.params.errors.forEach(($) => { + delete $.schemaPath; + }); + } }); t.deepEqual(validationError.errors, expectedErrors); } else { @@ -354,10 +359,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "pattern", - message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + errors: [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$", + } + }] }, }]); await assertValidation(t, { @@ -368,10 +380,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "minLength", - message: `should NOT be shorter than 3 characters`, + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 3, + errors: [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: "should NOT be shorter than 3 characters", + params: { + limit: 3, + }, + }] }, }]); await assertValidation(t, { @@ -382,10 +401,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "maxLength", - message: `should NOT be longer than 50 characters`, + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 50, + errors: [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: "should NOT be longer than 50 characters", + params: { + limit: 50, + }, + }] }, }]); }); diff --git a/test/lib/validation/schema/specVersion/kind/project/theme-library.js b/test/lib/validation/schema/specVersion/kind/project/theme-library.js index faca87799..220f193fa 100644 --- a/test/lib/validation/schema/specVersion/kind/project/theme-library.js +++ b/test/lib/validation/schema/specVersion/kind/project/theme-library.js @@ -358,10 +358,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "pattern", - message: `should match pattern "^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$"`, + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - pattern: `^(?:@[0-9a-z-_.]+/)?[a-z][0-9a-z-_.]*$`, + errors: [{ + dataPath: "/metadata/name", + keyword: "pattern", + message: `should match pattern "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$"`, + params: { + pattern: "^(?:@[0-9a-z-_.]+\\/)?[a-z][0-9a-z-_.]*$", + }, + }] }, }]); await assertValidation(t, { @@ -372,10 +379,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "minLength", - message: `should NOT be shorter than 3 characters`, + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 3, + errors: [{ + dataPath: "/metadata/name", + keyword: "minLength", + message: "should NOT be shorter than 3 characters", + params: { + limit: 3, + }, + }] }, }]); await assertValidation(t, { @@ -386,10 +400,17 @@ test.after.always((t) => { } }, [{ dataPath: "/metadata/name", - keyword: "maxLength", - message: `should NOT be longer than 50 characters`, + keyword: "errorMessage", + message: `Not a valid project name. It must consist of lowercase alphanumeric characters, dash, underscore and period only. Additionally, it may contain an npm-style package scope. For details see: https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name`, params: { - limit: 50, + errors: [{ + dataPath: "/metadata/name", + keyword: "maxLength", + message: "should NOT be longer than 50 characters", + params: { + limit: 50, + }, + }] }, }]); });