also looking at this
refactor: one update-type classifier, with the edge cases decided instead of accidental
#1439
4 files
+108
-116
| @@ -1,5 +1,6 @@ | ||
| 1 | 1 | import { describe, expect, it } from 'bun:test' |
| 2 | 2 | import { getUpdateType } from '../src/utils/helpers' |
| 3 | import { VersionResolver } from '../src/version/version-resolver' | |
| 3 | 4 | |
| 4 | 5 | describe('Version Classification', () => { |
| 5 | 6 | describe('getUpdateType', () => { |
| @@ -52,3 +53,53 @@ describe('Version Classification', () => { | ||
| 52 | 53 | }) |
| 53 | 54 | }) |
| 54 | 55 | }) |
| 56 | ||
| 57 | /** | |
| 58 | * Three parallel implementations of this classification existed — helpers, | |
| 59 | * a private Buddy method, and VersionResolver — and disagreed on short | |
| 60 | * actions tags, prereleases, suffixed Docker tags and non-semver input. | |
| 61 | * These pin the decided semantics of the one that remains. | |
| 62 | */ | |
| 63 | describe('one classifier across the codebase', () => { | |
| 64 | it('success case - a short actions tag reads as the bump it is', () => { | |
| 65 | // Bun.semver.order('4.2.2', '4') is -1 — without numeric padding the | |
| 66 | // upgrade guard misread this real upgrade as a downgrade. | |
| 67 | expect(getUpdateType('v4', 'v4.2.2')).toBe('minor') | |
| 68 | expect(getUpdateType('v4.2.2', 'v5')).toBe('major') | |
| 69 | }) | |
| 70 | ||
| 71 | it('success case - prerelease movement under an unchanged triple is a patch', () => { | |
| 72 | // These fell through to 'major', letting an excludeMajor filter block a | |
| 73 | // beta graduation as if it were a breaking change. | |
| 74 | expect(getUpdateType('1.0.0-beta.1', '1.0.0')).toBe('patch') | |
| 75 | expect(getUpdateType('1.0.0-beta.1', '1.0.0-beta.2')).toBe('patch') | |
| 76 | }) | |
| 77 | ||
| 78 | it('success case - a prerelease of the next major is still major', () => { | |
| 79 | expect(getUpdateType('1.0.0', '2.0.0-rc.1')).toBe('major') | |
| 80 | }) | |
| 81 | ||
| 82 | it('success case - suffixed docker tags classify by their numeric core', () => { | |
| 83 | expect(getUpdateType('3.19-alpine', '3.20-alpine')).toBe('minor') | |
| 84 | expect(getUpdateType('3.19-alpine', '4.0-alpine')).toBe('major') | |
| 85 | }) | |
| 86 | ||
| 87 | it('edge case - non-semver input degrades to patch, never a fabricated major', () => { | |
| 88 | expect(getUpdateType('latest', '1.0.0')).toBe('patch') | |
| 89 | expect(getUpdateType('workspace:*', '1.0.0')).toBe('patch') | |
| 90 | expect(getUpdateType('main', '1.0.0')).toBe('patch') | |
| 91 | }) | |
| 92 | ||
| 93 | it('success case - VersionResolver answers identically', () => { | |
| 94 | const cases: Array<[string, string]> = [ | |
| 95 | ['v4', 'v4.2.2'], | |
| 96 | ['v1.0.0', 'v2.0.0'], | |
| 97 | ['1.0.0-beta.1', '1.0.0'], | |
| 98 | ['latest', '1.0.0'], | |
| 99 | ['1.2.3', '1.3.0'], | |
| 100 | ] | |
| 101 | ||
| 102 | for (const [from, to] of cases) | |
| 103 | expect(VersionResolver.getUpdateType(from, to)).toBe(getUpdateType(from, to)) | |
| 104 | }) | |
| 105 | }) | |