Skip to content

Commit

Permalink
[INTERNAL] SpecVersionComparator: Refactor static methods, add JSDoc
Browse files Browse the repository at this point in the history
Static methods now create an instance and always throw for unsupported
versions (except isSupportedSpecVersion)
  • Loading branch information
RandomByte committed Nov 23, 2022
1 parent f01bb21 commit ef871e8
Show file tree
Hide file tree
Showing 4 changed files with 279 additions and 86 deletions.
15 changes: 8 additions & 7 deletions lib/specifications/Specification.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,9 @@ class Specification {
const config = JSON.parse(JSON.stringify(configuration));
const {validate} = await import("../validation/validator.js");

// SpecVersionComparator throws for invalid/unknown specVersion on instantiation
const specVersionComparator = new SpecVersionComparator(config.specVersion);
if (specVersionComparator.major() <= 1) {
if (SpecVersionComparator.major(config.specVersion) <= 1) {
const originalSpecVersion = config.specVersion;
this._log.verbose(`Detected legacy specification version ${config.specVersion}, defined for ` +
this._log.verbose(`Detected legacy Specification Version ${config.specVersion}, defined for ` +
`${config.kind} ${config.metadata.name}. ` +
`Attempting to migrate the project to a supported specification version...`);
this._migrateLegacyProject(config);
Expand All @@ -71,7 +69,7 @@ class Specification {
`Validation error after migration of ${config.kind} ${config.metadata.name}:`);
this._log.verbose(err.message);
throw new Error(
`${config.kind} ${config.metadata.name} defines unsupported specification version ` +
`${config.kind} ${config.metadata.name} defines unsupported Specification Version ` +
`${originalSpecVersion}. Please manually upgrade to 2.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, ` +
Expand Down Expand Up @@ -132,8 +130,11 @@ class Specification {
}

/**
* @public
*/
* Returns an instance of a helper class to compare the Specification Version with
*
* @public
* @returns {@ui5/project/specifications/utils/SpecVersionComparator}
*/
getSpecVersionComparator() {
return new SpecVersionComparator(this.getSpecVersion());
}
Expand Down
227 changes: 186 additions & 41 deletions lib/specifications/utils/SpecVersionComparator.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,90 +7,235 @@ const SUPPORTED_VERSIONS = [
"3.0"
];

/**
* Utility class for comparing Specification Versions
*
* @public
* @class
* @alias @ui5/project/specifications/utils/SpecVersionComparator
*/
class SpecVersionComparator {
constructor(specVersion) {
this._specVersion = specVersion;
#specVersion;
#semverVersion;

if (!SpecVersionComparator.isSupportedSpecVersion(specVersion)) {
throw new Error(getUnsupportedSpecVersionMessage(specVersion));
}
/**
* @param {string} specVersion Specification Version to use for all comparison operations
* @throws {Error} Throws if provided Specification Version is not supported by this version of @ui5/project
*/
constructor(specVersion) {
this.#specVersion = specVersion;
this.#semverVersion = getSemverCompatibleVersion(specVersion); // Throws for unsupported versions
}

/**
* Returns the major-version of the instance's Specification Version
*
* @returns {integer} Major version
*/
major() {
return SpecVersionComparator.major(this._specVersion);
return semver.major(this.#semverVersion);
}

/**
* Returns the minor-version of the instance's Specification Version
*
* @returns {integer} Minor version
*/
minor() {
return SpecVersionComparator.minor(this._specVersion);
return semver.minor(this.#semverVersion);
}

/**
* Test whether the instance's Specification Version falls into the provided range
*
* @param {string} range [Semver]{@link https://www.npmjs.com/package/semver}-style version range.
* For example <code>2.2 - 2.4</code>
* @returns {boolean} True if the instance's Specification Version falls into the provided range
*/
satisfies(range) {
return SpecVersionComparator.satisfies(this._specVersion);
return semver.satisfies(this.#semverVersion, range);
}

// Test whether project's specVersion is greater than testVersion
/**
* Test whether the instance's Specification Version is greater than the provided test version
*
* @param {string} testVersion A Specification Version to compare the instance's Specification Version to
* @returns {boolean} True if the instance's Specification Version is greater than the provided version
*/
gt(testVersion) {
return SpecVersionComparator.gt(this._specVersion, testVersion);
return handleSemverComparator(semver.gt, this.#semverVersion, testVersion);
}

/**
* Test whether the instance's Specification Version is greater than or equal the provided test version
*
* @param {string} testVersion A Specification Version to compare the instance's Specification Version to
* @returns {boolean} True if the instance's Specification Version is greater than or equal the provided version
*/
gte(testVersion) {
return SpecVersionComparator.gte(this._specVersion, testVersion);
return handleSemverComparator(semver.gte, this.#semverVersion, testVersion);
}

/**
* Test whether the instance's Specification Version is smaller than the provided test version
*
* @param {string} testVersion A Specification Version to compare the instance's Specification Version to
* @returns {boolean} True if the instance's Specification Version is smaller than the provided version
*/
lt(testVersion) {
return SpecVersionComparator.lt(this._specVersion, testVersion);
return handleSemverComparator(semver.lt, this.#semverVersion, testVersion);
}

/**
* Test whether the instance's Specification Version is smaller than or equal the provided test version
*
* @param {string} testVersion A Specification Version to compare the instance's Specification Version to
* @returns {boolean} True if the instance's Specification Version is smaller than or equal the provided version
*/
lte(testVersion) {
return SpecVersionComparator.lte(this._specVersion, testVersion);
return handleSemverComparator(semver.lte, this.#semverVersion, testVersion);
}

/**
* Test whether the instance's Specification Version is equal to the provided test version
*
* @param {string} testVersion A Specification Version to compare the instance's Specification Version to
* @returns {boolean} True if the instance's Specification Version is equal to the provided version
*/
eq(testVersion) {
return SpecVersionComparator.eq(this._specVersion, testVersion);
return handleSemverComparator(semver.eq, this.#semverVersion, testVersion);
}

/**
* Test whether the instance's Specification Version is not equal to the provided test version
*
* @param {string} testVersion A Specification Version to compare the instance's Specification Version to
* @returns {boolean} True if the instance's Specification Version is not equal to the provided version
*/
neq(testVersion) {
return SpecVersionComparator.neq(this._specVersion, testVersion);
return handleSemverComparator(semver.neq, this.#semverVersion, testVersion);
}

static isSupportedSpecVersion(specVersion) {
return SUPPORTED_VERSIONS.includes(specVersion);
/**
* Test whether the provided Specification Version is supported by this version of @ui5/project
*
* @param {string} testVersion A Specification Version to compare the instance's Specification Version to
* @returns {boolean} True if the provided Specification Version is supported
*/
static isSupportedSpecVersion(testVersion) {
return SUPPORTED_VERSIONS.includes(testVersion);
}

/**
* Returns the major-version of provided Specification Version
*
* @param {string} specVersion Specification Version
* @returns {integer} Major version
*/
static major(specVersion) {
const version = getSemverCompatibleVersion(specVersion);
return semver.major(version);
const comparator = new SpecVersionComparator(specVersion);
return comparator.major();
}

/**
* Returns the minor-version of the provided Specification Version
*
* @param {string} specVersion Specification Version
* @returns {integer} Minor version
*/
static minor(specVersion) {
const version = getSemverCompatibleVersion(specVersion);
return semver.minor(version);
const comparator = new SpecVersionComparator(specVersion);
return comparator.minor();
}

/**
* Test whether the provided Specification Version falls into the provided range
*
* @param {string} specVersion Specification Version
* @param {string} range [Semver]{@link https://www.npmjs.com/package/semver}-style version range.
* For example <code>2.2 - 2.4</code>
* @returns {boolean} True if the provided Specification Version falls into the provided range
*/
static satisfies(specVersion, range) {
const version = getSemverCompatibleVersion(specVersion);
return semver.satisfies(version, range);
const comparator = new SpecVersionComparator(specVersion);
return comparator.satisfies(range);
}
static gt(specVersion, expectedVersion) {
return handleSemverComparator(semver.gt, specVersion, expectedVersion);

/**
* Test whether the provided Specification Version is greater than the provided test version
*
* @param {string} specVersion Specification Version
* @param {string} testVersion A Specification Version to compare the provided Specification Version to
* @returns {boolean} True if the provided Specification Version is greater than the provided version
*/
static gt(specVersion, testVersion) {
const comparator = new SpecVersionComparator(specVersion);
return comparator.gt(testVersion);
}
static gte(specVersion, expectedVersion) {
return handleSemverComparator(semver.gte, specVersion, expectedVersion);

/**
* Test whether the provided Specification Version is greater than or equal the provided test version
*
* @param {string} specVersion Specification Version
* @param {string} testVersion A Specification Version to compare the provided Specification Version to
* @returns {boolean} True if the provided Specification Version is greater than or equal the provided version
*/
static gte(specVersion, testVersion) {
const comparator = new SpecVersionComparator(specVersion);
return comparator.gte(testVersion);
}
static lt(specVersion, expectedVersion) {
return handleSemverComparator(semver.lt, specVersion, expectedVersion);

/**
* Test whether the provided Specification Version is smaller than the provided test version
*
* @param {string} specVersion Specification Version
* @param {string} testVersion A Specification Version to compare the provided Specification Version to
* @returns {boolean} True if the provided Specification Version is smaller than the provided version
*/
static lt(specVersion, testVersion) {
const comparator = new SpecVersionComparator(specVersion);
return comparator.lt(testVersion);
}
static lte(specVersion, expectedVersion) {
return handleSemverComparator(semver.lte, specVersion, expectedVersion);

/**
* Test whether the provided Specification Version is smaller than or equal the provided test version
*
* @param {string} specVersion Specification Version
* @param {string} testVersion A Specification Version to compare the provided Specification Version to
* @returns {boolean} True if the provided Specification Version is smaller than or equal the provided version
*/
static lte(specVersion, testVersion) {
const comparator = new SpecVersionComparator(specVersion);
return comparator.lte(testVersion);
}
static eq(specVersion, expectedVersion) {
return handleSemverComparator(semver.eq, specVersion, expectedVersion);

/**
* Test whether the provided Specification Version is equal to the provided test version
*
* @param {string} specVersion Specification Version
* @param {string} testVersion A Specification Version to compare the provided Specification Version to
* @returns {boolean} True if the provided Specification Version is equal to the provided version
*/
static eq(specVersion, testVersion) {
const comparator = new SpecVersionComparator(specVersion);
return comparator.eq(testVersion);
}
static neq(specVersion, expectedVersion) {
return handleSemverComparator(semver.neq, specVersion, expectedVersion);

/**
* Test whether the provided Specification Version is not equal to the provided test version
*
* @param {string} specVersion Specification Version
* @param {string} testVersion A Specification Version to compare the provided Specification Version to
* @returns {boolean} True if the provided Specification Version is not equal to the provided version
*/
static neq(specVersion, testVersion) {
const comparator = new SpecVersionComparator(specVersion);
return comparator.neq(testVersion);
}
}

function getUnsupportedSpecVersionMessage(specVersion) {
return `Unsupported specification version ${specVersion} defined. Your UI5 CLI installation might be outdated. ` +
return `Unsupported Specification Version ${specVersion} defined. Your UI5 CLI installation might be outdated. ` +
`For details see https://sap.github.io/ui5-tooling/pages/Configuration/#specification-versions`;
}

Expand All @@ -101,13 +246,13 @@ function getSemverCompatibleVersion(specVersion) {
throw new Error(getUnsupportedSpecVersionMessage(specVersion));
}

function handleSemverComparator(comparator, specVersion, expectedVersion) {
if (SPEC_VERSION_PATTERN.test(expectedVersion)) {
const a = getSemverCompatibleVersion(specVersion);
const b = expectedVersion + ".0";
function handleSemverComparator(comparator, baseVersion, testVersion) {
if (SPEC_VERSION_PATTERN.test(testVersion)) {
const a = baseVersion;
const b = testVersion + ".0";
return comparator(a, b);
}
throw new Error("Invalid spec version expectation given in comparator: " + expectedVersion);
throw new Error("Invalid spec version expectation given in comparator: " + testVersion);
}

export default SpecVersionComparator;
Expand Down
4 changes: 2 additions & 2 deletions test/lib/specifications/Specification.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,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 2.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.",
Expand Down Expand Up @@ -295,7 +295,7 @@ test("Invalid specVersion", async (t) => {
t.context.basicProjectInput.configuration.specVersion = "0.5";
await t.throwsAsync(Specification.create(t.context.basicProjectInput), {
message:
"Unsupported specification version 0.5 defined. Your UI5 CLI installation might be outdated. " +
"Unsupported Specification Version 0.5 defined. Your UI5 CLI installation might be outdated. " +
"For details see https://sap.github.io/ui5-tooling/pages/Configuration/#specification-versions"
}, "Threw with expected error message");
});
Loading

0 comments on commit ef871e8

Please sign in to comment.