fix: return error on invalid ordinal with points

Previously, if the ordinal contained dots (like 1.2.3-beta.3.4.5),
although it was invalid, an error would not be returned, which was
problematic. This has now been fixed.

Test cases are also included to prevent future regressions.
This commit is contained in:
Erica Marigold 2024-11-21 18:21:19 +00:00
parent ab6e993879
commit fe321dda7b
2 changed files with 136 additions and 108 deletions

View file

@ -293,11 +293,9 @@ function Semver.parse(ver: string): SemverResult<SemverImpl>
-- b) The component has build metadata after prerelease info
-- Here, we handle both those cases
local potentialOrdinalNumber, potentialBuildMetadata = string.match(components[4], "(%d)+(.*)")
local potentialOrdinalNumber, potentialBuildMetadata = string.match(components[4], "(.*)+(.*)")
if potentialOrdinalNumber == nil then
return badPrereleaseType(components[4])
-- TODO: If there are components after the 4th index, we
-- should error
end
if potentialBuildMetadata ~= nil then
@ -315,6 +313,14 @@ function Semver.parse(ver: string): SemverResult<SemverImpl>
return badPrereleaseType(components[4])
end
end
elseif #components > 4 then
-- The ordinal component was bad, we should error
local badPrerelease = ""
for i = 4, #components do
badPrerelease ..= "." .. components[i]
end
return badPrereleaseType(badPrerelease)
end
prereleaseOrdinal = Option.Some(ordinalNum :: number) :: Option<number>

View file

@ -5,118 +5,140 @@ local check = frktest.assert.check
local Semver = require("../lib")
return function()
test.suite("Invalid semver parsing tests", function()
test.case("Rejects missing components", function()
local res = Semver.parse("1.2")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "MandatoryComponentMissing",
components = { "1", "2" },
},
})
end)
test.suite("Invalid semver parsing tests", function()
test.case("Rejects missing components", function()
local res = Semver.parse("1.2")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "MandatoryComponentMissing",
components = { "1", "2" },
},
})
end)
test.case("Rejects invalid component types", function()
-- Test invalid major
local res = Semver.parse("a.2.3")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidComponentType",
component = "major",
got = "char",
},
})
test.case("Rejects invalid component types", function()
-- Test invalid major
local res = Semver.parse("a.2.3")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidComponentType",
component = "major",
got = "char",
},
})
-- Test invalid minor with symbols
res = Semver.parse("1.$.3")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidComponentType",
component = "minor",
got = "symbol",
},
})
-- Test invalid minor with symbols
res = Semver.parse("1.$.3")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidComponentType",
component = "minor",
got = "symbol",
},
})
-- Test invalid patch
res = Semver.parse("1.2.x")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidComponentType",
component = "patch",
got = "char",
},
})
end)
-- Test invalid patch
res = Semver.parse("1.2.x")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidComponentType",
component = "patch",
got = "char",
},
})
end)
test.case("Rejects leading zeros", function()
-- Test leading zeros in major
local res = Semver.parse("01.2.3")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "LeadingZerosPresent",
component = "major",
},
})
test.case("Rejects leading zeros", function()
-- Test leading zeros in major
local res = Semver.parse("01.2.3")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "LeadingZerosPresent",
component = "major",
},
})
-- Test leading zeros in minor
res = Semver.parse("1.02.3")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "LeadingZerosPresent",
component = "minor",
},
})
-- Test leading zeros in minor
res = Semver.parse("1.02.3")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "LeadingZerosPresent",
component = "minor",
},
})
-- Test leading zeros in patch
res = Semver.parse("1.2.03")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "LeadingZerosPresent",
component = "patch",
},
})
end)
-- Test leading zeros in patch
res = Semver.parse("1.2.03")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "LeadingZerosPresent",
component = "patch",
},
})
end)
test.case("Rejects invalid prerelease types", function()
local res = Semver.parse("1.2.3-gamma.1")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidPrereleaseType",
type = "gamma",
},
})
end)
test.case("Rejects invalid prerelease types", function()
local res = Semver.parse("1.2.3-gamma.1")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidPrereleaseType",
type = "gamma",
},
})
end)
test.case("Rejects invalid prerelease ordinals", function()
-- Test with character ordinal
local res = Semver.parse("1.2.3-beta.a")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidPrereleaseOrdinalType",
expected = "number",
got = "char",
},
})
test.case("Rejects invalid prerelease ordinals", function()
-- Test with character ordinal
local res = Semver.parse("1.2.3-beta.a")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidPrereleaseOrdinalType",
expected = "number",
got = "char",
},
})
-- Test with symbol ordinal
res = Semver.parse("1.2.3-beta.$")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidPrereleaseOrdinalType",
expected = "number",
got = "symbol",
},
})
end)
end)
-- Test with symbol ordinal
res = Semver.parse("1.2.3-beta.$")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidPrereleaseOrdinalType",
expected = "number",
got = "symbol",
},
})
-- Test with extra symbols in ordinal
res = Semver.parse("1.2.3-beta.3.4.5")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidPrereleaseOrdinalType",
expected = "number",
got = "symbol",
},
})
-- Test with extra symbols in ordinal and build metadata
res = Semver.parse("1.2.3-beta.3.4.5+build.1732213169")
check.is_true(res:isErr())
check.table.contains(res:unwrapErr(), {
kind = {
id = "InvalidPrereleaseOrdinalType",
expected = "number",
got = "symbol",
},
})
end)
end)
end