-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce a utility module which handles SpecVersion comparators for an easier SpecVersion maintainance within the UI5 Tooling source code. This utility is a kind of semver compatibility layer which allows using semver functions with the SpecVersion typical format "Major.Minor". JIRA: CPOUI5FOUNDATION-224
- Loading branch information
1 parent
159a4c3
commit 5d3e8d7
Showing
2 changed files
with
206 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
const semver = require("semver"); | ||
|
||
const SPEC_VERSION_PATTERN = /^\d+\.\d+$/; | ||
const SUPPORTED_VERSIONS = [ | ||
"0.1", "1.0", "1.1", | ||
"2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6" | ||
]; | ||
|
||
function isSupportedSpecVersion(specVersion) { | ||
return SUPPORTED_VERSIONS.includes(specVersion); | ||
} | ||
|
||
function getSemverCompatibleVersion(specVersion) { | ||
if (isSupportedSpecVersion(specVersion)) { | ||
return specVersion + ".0"; | ||
} | ||
// TODO 3.0: sync error text with error of projectPreprocessor.js | ||
throw new Error( | ||
`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`); | ||
} | ||
|
||
function major(specVersion) { | ||
const version = getSemverCompatibleVersion(specVersion); | ||
return semver.major(version); | ||
} | ||
|
||
function minor(specVersion) { | ||
const version = getSemverCompatibleVersion(specVersion); | ||
return semver.minor(version); | ||
} | ||
|
||
function satisfies(specVersion, range) { | ||
const version = getSemverCompatibleVersion(specVersion); | ||
return semver.satisfies(version, range); | ||
} | ||
|
||
function handleSemverComparator(comparator, specVersion, expectedVersion) { | ||
if (SPEC_VERSION_PATTERN.test(expectedVersion)) { | ||
const a = getSemverCompatibleVersion(specVersion); | ||
const b = expectedVersion + ".0"; | ||
return comparator(a, b); | ||
} | ||
throw new Error("Invalid spec version expectation given in comparator: " + expectedVersion); | ||
} | ||
const gt = (specVersion, expectedVersion) => handleSemverComparator(semver.gt, specVersion, expectedVersion); | ||
const gte = (specVersion, expectedVersion) => handleSemverComparator(semver.gte, specVersion, expectedVersion); | ||
const lt = (specVersion, expectedVersion) => handleSemverComparator(semver.lt, specVersion, expectedVersion); | ||
const lte = (specVersion, expectedVersion) => handleSemverComparator(semver.lte, specVersion, expectedVersion); | ||
const eq = (specVersion, expectedVersion) => handleSemverComparator(semver.eq, specVersion, expectedVersion); | ||
const neq = (specVersion, expectedVersion) => handleSemverComparator(semver.neq, specVersion, expectedVersion); | ||
|
||
module.exports = { | ||
isSupportedSpecVersion, | ||
// semver functions | ||
major, | ||
minor, | ||
satisfies, | ||
gt, | ||
gte, | ||
lt, | ||
lte, | ||
eq, | ||
neq | ||
}; | ||
|
||
// Export local function for testing only | ||
if (process.env.NODE_ENV === "test") { | ||
module.exports._getSemverCompatibleVersion = getSemverCompatibleVersion; | ||
module.exports._handleSemverComparator = handleSemverComparator; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
const test = require("ava"); | ||
const sinon = require("sinon"); | ||
const SpecVersionUtil = require("../../lib/SpecVersionUtil"); | ||
|
||
const unsupportedSpecVersionText = (specVersion) => | ||
`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`; | ||
|
||
test("isSupportedSpecVersion", (t) => { | ||
t.is(SpecVersionUtil.isSupportedSpecVersion("0.1"), true); | ||
t.is(SpecVersionUtil.isSupportedSpecVersion("1.0"), true); | ||
t.is(SpecVersionUtil.isSupportedSpecVersion("1.1"), true); | ||
t.is(SpecVersionUtil.isSupportedSpecVersion("2.0"), true); | ||
t.is(SpecVersionUtil.isSupportedSpecVersion("2.4"), true); | ||
t.is(SpecVersionUtil.isSupportedSpecVersion("0.2"), false); | ||
t.is(SpecVersionUtil.isSupportedSpecVersion("1.2"), false); | ||
t.is(SpecVersionUtil.isSupportedSpecVersion(1.1), false); | ||
t.is(SpecVersionUtil.isSupportedSpecVersion("foo"), false); | ||
t.is(SpecVersionUtil.isSupportedSpecVersion(""), false); | ||
t.is(SpecVersionUtil.isSupportedSpecVersion(), false); | ||
}); | ||
|
||
test("major", (t) => { | ||
t.is(SpecVersionUtil.major("0.1"), 0); | ||
t.is(SpecVersionUtil.major("1.1"), 1); | ||
t.is(SpecVersionUtil.major("2.1"), 2); | ||
|
||
t.is(t.throws(() => { | ||
SpecVersionUtil.major("0.2"); | ||
}).message, unsupportedSpecVersionText("0.2")); | ||
}); | ||
|
||
test("minor", (t) => { | ||
t.is(SpecVersionUtil.minor("2.1"), 1); | ||
t.is(SpecVersionUtil.minor("2.2"), 2); | ||
t.is(SpecVersionUtil.minor("2.3"), 3); | ||
|
||
t.is(t.throws(() => { | ||
SpecVersionUtil.minor("1.2"); | ||
}).message, unsupportedSpecVersionText("1.2")); | ||
}); | ||
|
||
test("satisfies", (t) => { | ||
// range: 1.x | ||
t.is(SpecVersionUtil.satisfies("1.0", "1.x"), true); | ||
t.is(SpecVersionUtil.satisfies("1.1", "1.x"), true); | ||
t.is(SpecVersionUtil.satisfies("2.0", "1.x"), false); | ||
|
||
// range: ^2.2 | ||
t.is(SpecVersionUtil.satisfies("2.1", "^2.2"), false); | ||
t.is(SpecVersionUtil.satisfies("2.2", "^2.2"), true); | ||
t.is(SpecVersionUtil.satisfies("2.3", "^2.2"), true); | ||
|
||
// range: > 1.0 | ||
t.is(SpecVersionUtil.satisfies("1.0", "> 1.0"), false); | ||
t.is(SpecVersionUtil.satisfies("1.1", "> 1.0"), true); | ||
t.is(SpecVersionUtil.satisfies("2.2", "> 1.0"), true); | ||
|
||
// range: 2.2 - 2.4 | ||
t.is(SpecVersionUtil.satisfies("2.1", "2.2 - 2.4"), false); | ||
t.is(SpecVersionUtil.satisfies("2.2", "2.2 - 2.4"), true); | ||
t.is(SpecVersionUtil.satisfies("2.3", "2.2 - 2.4"), true); | ||
t.is(SpecVersionUtil.satisfies("2.4", "2.2 - 2.4"), true); | ||
t.is(SpecVersionUtil.satisfies("2.5", "2.2 - 2.4"), false); | ||
|
||
// range: 0.1 || 1.0 - 1.1 || ^2.5 | ||
t.is(SpecVersionUtil.satisfies("0.1", "0.1 || 1.0 - 1.1 || ^2.5"), true); | ||
t.is(SpecVersionUtil.satisfies("1.0", "0.1 || 1.0 - 1.1 || ^2.5"), true); | ||
t.is(SpecVersionUtil.satisfies("1.1", "0.1 || 1.0 - 1.1 || ^2.5"), true); | ||
t.is(SpecVersionUtil.satisfies("2.4", "0.1 || 1.0 - 1.1 || ^2.5"), false); | ||
t.is(SpecVersionUtil.satisfies("2.5", "0.1 || 1.0 - 1.1 || ^2.5"), true); | ||
t.is(SpecVersionUtil.satisfies("2.6", "0.1 || 1.0 - 1.1 || ^2.5"), true); | ||
|
||
// unsupported spec version | ||
t.is(t.throws(() => { | ||
SpecVersionUtil.satisfies("0.2", "1.x"); | ||
}).message, unsupportedSpecVersionText("0.2")); | ||
}); | ||
|
||
test("low level comparator", (t) => { | ||
t.is(SpecVersionUtil.gt("2.1", "2.2"), false); | ||
t.is(SpecVersionUtil.gt("2.2", "2.2"), false); | ||
t.is(SpecVersionUtil.gt("2.3", "2.2"), true); | ||
|
||
t.is(SpecVersionUtil.gte("2.1", "2.2"), false); | ||
t.is(SpecVersionUtil.gte("2.2", "2.2"), true); | ||
t.is(SpecVersionUtil.gte("2.3", "2.2"), true); | ||
|
||
t.is(SpecVersionUtil.lt("2.1", "2.2"), true); | ||
t.is(SpecVersionUtil.lt("2.2", "2.2"), false); | ||
t.is(SpecVersionUtil.lt("2.3", "2.2"), false); | ||
|
||
t.is(SpecVersionUtil.lte("2.1", "2.2"), true); | ||
t.is(SpecVersionUtil.lte("2.2", "2.2"), true); | ||
t.is(SpecVersionUtil.lte("2.3", "2.2"), false); | ||
|
||
t.is(SpecVersionUtil.eq("2.0", "2.2"), false); | ||
t.is(SpecVersionUtil.eq("2.2", "2.2"), true); | ||
|
||
t.is(SpecVersionUtil.neq("2.0", "2.2"), true); | ||
t.is(SpecVersionUtil.neq("2.2", "2.2"), false); | ||
}); | ||
|
||
test("getSemverCompatibleVersion", (t) => { | ||
t.is(SpecVersionUtil._getSemverCompatibleVersion("0.1"), "0.1.0"); | ||
t.is(SpecVersionUtil._getSemverCompatibleVersion("1.1"), "1.1.0"); | ||
t.is(SpecVersionUtil._getSemverCompatibleVersion("2.0"), "2.0.0"); | ||
|
||
t.is(t.throws(() => { | ||
SpecVersionUtil._getSemverCompatibleVersion("1.2.3"); | ||
}).message, unsupportedSpecVersionText("1.2.3")); | ||
t.is(t.throws(() => { | ||
SpecVersionUtil._getSemverCompatibleVersion("0.99"); | ||
}).message, unsupportedSpecVersionText("0.99")); | ||
t.is(t.throws(() => { | ||
SpecVersionUtil._getSemverCompatibleVersion("foo"); | ||
}).message, unsupportedSpecVersionText("foo")); | ||
t.is(t.throws(() => { | ||
SpecVersionUtil._getSemverCompatibleVersion(); | ||
}).message, unsupportedSpecVersionText("undefined")); | ||
}); | ||
|
||
test("handleSemverComparator", (t) => { | ||
const comparatorStub = sinon.stub().returns("foobar"); | ||
t.is(SpecVersionUtil._handleSemverComparator(comparatorStub, "1.1", "2.2"), "foobar"); | ||
t.deepEqual(comparatorStub.getCall(0).args, ["1.1.0", "2.2.0"]); | ||
|
||
t.is(t.throws(() => { | ||
SpecVersionUtil._handleSemverComparator(undefined, "a.b", "2.2"); | ||
}).message, unsupportedSpecVersionText("a.b")); | ||
|
||
t.is(t.throws(() => { | ||
SpecVersionUtil._handleSemverComparator(undefined, undefined, "a.b"); | ||
}).message, "Invalid spec version expectation given in comparator: a.b"); | ||
}); |