semver.test.ts 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import { describe, expect, it } from 'vitest'
  2. import {
  3. compareSemver,
  4. isEqual,
  5. isGreaterThan,
  6. isGreaterThanOrEqual,
  7. isLessThan,
  8. isLessThanOrEqual,
  9. isValidSemver,
  10. parseSemver,
  11. } from './semver'
  12. describe('parseSemver', () => {
  13. it('should parse valid semver strings', () => {
  14. expect(parseSemver('1.2.3')).toEqual({ major: 1, minor: 2, patch: 3 })
  15. expect(parseSemver('0.0.1')).toEqual({ major: 0, minor: 0, patch: 1 })
  16. expect(parseSemver('10.20.30')).toEqual({ major: 10, minor: 20, patch: 30 })
  17. })
  18. it('should parse versions with fewer than 3 parts', () => {
  19. expect(parseSemver('1')).toEqual({ major: 1, minor: 0, patch: 0 })
  20. expect(parseSemver('1.5')).toEqual({ major: 1, minor: 5, patch: 0 })
  21. })
  22. it('should return null for versions with more than 3 parts', () => {
  23. expect(parseSemver('1.2.3.4')).toBeNull()
  24. expect(parseSemver('1.2.3.4.5')).toBeNull()
  25. })
  26. it('should handle strings with extra whitespace', () => {
  27. expect(parseSemver(' 1.2.3 ')).toEqual({ major: 1, minor: 2, patch: 3 })
  28. expect(parseSemver(' 1.2.3 ')).toEqual({ major: 1, minor: 2, patch: 3 })
  29. })
  30. it('should return null for invalid semver strings', () => {
  31. expect(parseSemver('1.2.x')).toBeNull()
  32. expect(parseSemver('a.b.c')).toBeNull()
  33. expect(parseSemver('')).toBeNull()
  34. expect(parseSemver('invalid')).toBeNull()
  35. })
  36. it('should return null for negative numbers', () => {
  37. expect(parseSemver('-1.2.3')).toBeNull()
  38. expect(parseSemver('1.-2.3')).toBeNull()
  39. expect(parseSemver('1.2.-3')).toBeNull()
  40. })
  41. it('should return null for non-string inputs', () => {
  42. expect(parseSemver(null as any)).toBeNull()
  43. expect(parseSemver(undefined as any)).toBeNull()
  44. expect(parseSemver(123 as any)).toBeNull()
  45. })
  46. })
  47. describe('compareSemver', () => {
  48. it('should return 0 for equal versions', () => {
  49. expect(compareSemver('1.2.3', '1.2.3')).toBe(0)
  50. expect(compareSemver('0.0.0', '0.0.0')).toBe(0)
  51. expect(compareSemver('10.20.30', '10.20.30')).toBe(0)
  52. })
  53. it('should return 1 when first version is greater', () => {
  54. expect(compareSemver('2.0.0', '1.0.0')).toBe(1)
  55. expect(compareSemver('1.3.0', '1.2.0')).toBe(1)
  56. expect(compareSemver('1.2.4', '1.2.3')).toBe(1)
  57. expect(compareSemver('2.0.0', '1.9.9')).toBe(1)
  58. })
  59. it('should return -1 when first version is less', () => {
  60. expect(compareSemver('1.0.0', '2.0.0')).toBe(-1)
  61. expect(compareSemver('1.2.0', '1.3.0')).toBe(-1)
  62. expect(compareSemver('1.2.3', '1.2.4')).toBe(-1)
  63. expect(compareSemver('1.9.9', '2.0.0')).toBe(-1)
  64. })
  65. it('should return null for invalid versions', () => {
  66. expect(compareSemver('1.2.3', 'invalid')).toBeNull()
  67. expect(compareSemver('invalid', '1.2.3')).toBeNull()
  68. })
  69. it('should prioritize major version differences', () => {
  70. expect(compareSemver('2.0.0', '1.99.99')).toBe(1)
  71. expect(compareSemver('1.99.99', '2.0.0')).toBe(-1)
  72. })
  73. it('should prioritize minor version differences when major is equal', () => {
  74. expect(compareSemver('1.3.0', '1.2.99')).toBe(1)
  75. expect(compareSemver('1.2.99', '1.3.0')).toBe(-1)
  76. })
  77. it('should compare variable-length versions treating missing parts as 0', () => {
  78. expect(compareSemver('1.5', '1.5.0')).toBe(0)
  79. expect(compareSemver('1.5.0', '1.5')).toBe(0)
  80. expect(compareSemver('1', '1.0.0')).toBe(0)
  81. expect(compareSemver('1.5', '1.5.1')).toBe(-1)
  82. expect(compareSemver('1.5.1', '1.5')).toBe(1)
  83. expect(compareSemver('2', '1.9.9')).toBe(1)
  84. expect(compareSemver('1.9.9', '2')).toBe(-1)
  85. })
  86. it('should return null for versions with more than 3 parts', () => {
  87. expect(compareSemver('1.2.3.4', '1.2.3')).toBeNull()
  88. expect(compareSemver('1.2.3', '1.2.3.4')).toBeNull()
  89. })
  90. })
  91. describe('isGreaterThan', () => {
  92. it('should return true when first version is greater', () => {
  93. expect(isGreaterThan('2.0.0', '1.0.0')).toBe(true)
  94. expect(isGreaterThan('1.3.0', '1.2.0')).toBe(true)
  95. expect(isGreaterThan('1.2.4', '1.2.3')).toBe(true)
  96. })
  97. it('should return false when first version is not greater', () => {
  98. expect(isGreaterThan('1.0.0', '2.0.0')).toBe(false)
  99. expect(isGreaterThan('1.2.3', '1.2.3')).toBe(false)
  100. expect(isGreaterThan('1.2.3', 'invalid')).toBe(false)
  101. })
  102. })
  103. describe('isLessThan', () => {
  104. it('should return true when first version is less', () => {
  105. expect(isLessThan('1.0.0', '2.0.0')).toBe(true)
  106. expect(isLessThan('1.2.0', '1.3.0')).toBe(true)
  107. expect(isLessThan('1.2.3', '1.2.4')).toBe(true)
  108. })
  109. it('should return false when first version is not less', () => {
  110. expect(isLessThan('2.0.0', '1.0.0')).toBe(false)
  111. expect(isLessThan('1.2.3', '1.2.3')).toBe(false)
  112. expect(isLessThan('1.2.3', 'invalid')).toBe(false)
  113. })
  114. })
  115. describe('isEqual', () => {
  116. it('should return true when versions are equal', () => {
  117. expect(isEqual('1.2.3', '1.2.3')).toBe(true)
  118. expect(isEqual('0.0.0', '0.0.0')).toBe(true)
  119. expect(isEqual('10.20.30', '10.20.30')).toBe(true)
  120. })
  121. it('should return false when versions are not equal', () => {
  122. expect(isEqual('1.2.3', '1.2.4')).toBe(false)
  123. expect(isEqual('1.2.3', '2.2.3')).toBe(false)
  124. expect(isEqual('1.2.3', 'invalid')).toBe(false)
  125. })
  126. })
  127. describe('isGreaterThanOrEqual', () => {
  128. it('should return true when first version is greater or equal', () => {
  129. expect(isGreaterThanOrEqual('2.0.0', '1.0.0')).toBe(true)
  130. expect(isGreaterThanOrEqual('1.2.3', '1.2.3')).toBe(true)
  131. expect(isGreaterThanOrEqual('1.2.4', '1.2.3')).toBe(true)
  132. })
  133. it('should return false when first version is less', () => {
  134. expect(isGreaterThanOrEqual('1.0.0', '2.0.0')).toBe(false)
  135. expect(isGreaterThanOrEqual('1.2.3', 'invalid')).toBe(false)
  136. })
  137. it('should handle variable-length versions', () => {
  138. expect(isGreaterThanOrEqual('1.5', '1.5')).toBe(true)
  139. expect(isGreaterThanOrEqual('1.6', '1.5')).toBe(true)
  140. expect(isGreaterThanOrEqual('1.4', '1.5')).toBe(false)
  141. expect(isGreaterThanOrEqual('1.5.0', '1.5')).toBe(true)
  142. expect(isGreaterThanOrEqual('1.5.1', '1.5')).toBe(true)
  143. expect(isGreaterThanOrEqual('2', '1.5')).toBe(true)
  144. expect(isGreaterThanOrEqual('1', '1.5')).toBe(false)
  145. })
  146. })
  147. describe('isLessThanOrEqual', () => {
  148. it('should return true when first version is less or equal', () => {
  149. expect(isLessThanOrEqual('1.0.0', '2.0.0')).toBe(true)
  150. expect(isLessThanOrEqual('1.2.3', '1.2.3')).toBe(true)
  151. expect(isLessThanOrEqual('1.2.3', '1.2.4')).toBe(true)
  152. })
  153. it('should return false when first version is greater', () => {
  154. expect(isLessThanOrEqual('2.0.0', '1.0.0')).toBe(false)
  155. expect(isLessThanOrEqual('1.2.3', 'invalid')).toBe(false)
  156. })
  157. })
  158. describe('isValidSemver', () => {
  159. it('should return true for valid semver strings', () => {
  160. expect(isValidSemver('1.2.3')).toBe(true)
  161. expect(isValidSemver('0.0.0')).toBe(true)
  162. expect(isValidSemver('10.20.30')).toBe(true)
  163. })
  164. it('should return true for versions with 1-3 parts', () => {
  165. expect(isValidSemver('1')).toBe(true)
  166. expect(isValidSemver('1.2')).toBe(true)
  167. })
  168. it('should return false for versions with more than 3 parts', () => {
  169. expect(isValidSemver('1.2.3.4')).toBe(false)
  170. })
  171. it('should return false for invalid semver strings', () => {
  172. expect(isValidSemver('invalid')).toBe(false)
  173. expect(isValidSemver('')).toBe(false)
  174. expect(isValidSemver('1.x.3')).toBe(false)
  175. })
  176. })