Twenty-nine commits since v0.12.0. See CHANGELOG.md for the full list and the upgrade notes. Ten additions — the SEO package (site URL, robots.txt, sitemap.xml, JSON-LD), slideshow mode, opt-in original downloads, copy-link, previous/next album navigation, alt text from the Immich description, per-album location precision, the update notice, a Help tab, and a subpage cover grid separate from its photo grid. Two fixes: CJK album slugs, and the lightbox control bar. Photo of the Day (#476) was built on `dev` and reverted as not planned; it never appears in a release. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01DmsHVRL9yQvckUB1ZpVWre --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: ralksta <ralksta@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
91 lines
3.5 KiB
TypeScript
91 lines
3.5 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { compareVersions, isNewerVersion, parseLatestTag } from '@/lib/updateCheck';
|
|
|
|
describe('compareVersions', () => {
|
|
it.each([
|
|
['0.12.0', '0.12.0', 0],
|
|
['0.12.1', '0.12.0', 1],
|
|
['0.12.0', '0.12.1', -1],
|
|
['1.0.0', '0.99.99', 1],
|
|
['0.13.0', '0.9.0', 1],
|
|
])('%s vs %s', (a, b, expected) => {
|
|
expect(Math.sign(compareVersions(a, b))).toBe(expected);
|
|
});
|
|
|
|
/** 10 must not sort before 9, which is what a string compare would do. */
|
|
it('compares numerically, not lexically', () => {
|
|
expect(compareVersions('0.10.0', '0.9.0')).toBeGreaterThan(0);
|
|
expect(compareVersions('0.2.0', '0.10.0')).toBeLessThan(0);
|
|
});
|
|
|
|
it('tolerates the leading v the releases API uses', () => {
|
|
expect(compareVersions('v0.12.0', '0.12.0')).toBe(0);
|
|
expect(compareVersions('V0.13.0', '0.12.0')).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('treats missing segments as zero', () => {
|
|
expect(compareVersions('1', '1.0.0')).toBe(0);
|
|
expect(compareVersions('1.1', '1.0.9')).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('compares a pre-release on its numbers alone', () => {
|
|
expect(compareVersions('0.13.0-rc.1', '0.12.0')).toBeGreaterThan(0);
|
|
expect(compareVersions('0.12.0-rc.1', '0.12.0')).toBe(0);
|
|
});
|
|
|
|
it('does not crash on rubbish', () => {
|
|
expect(() => compareVersions('', 'x.y.z')).not.toThrow();
|
|
expect(compareVersions('x.y.z', '')).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe('isNewerVersion', () => {
|
|
it('is true only for a strictly newer release', () => {
|
|
expect(isNewerVersion('0.13.0', '0.12.0')).toBe(true);
|
|
expect(isNewerVersion('0.12.0', '0.12.0')).toBe(false);
|
|
expect(isNewerVersion('0.11.0', '0.12.0')).toBe(false);
|
|
});
|
|
|
|
/** A downgraded tag must never be advertised as an update. */
|
|
it('does not nag when running ahead of the latest release', () => {
|
|
expect(isNewerVersion('v0.12.0', '0.13.0-dev')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('parseLatestTag', () => {
|
|
it('reads tag_name', () => {
|
|
expect(parseLatestTag({ tag_name: 'v0.13.0' })).toBe('v0.13.0');
|
|
});
|
|
|
|
it('trims surrounding whitespace', () => {
|
|
expect(parseLatestTag({ tag_name: ' v0.13.0 ' })).toBe('v0.13.0');
|
|
});
|
|
|
|
it.each([
|
|
['null', null],
|
|
['a string', 'v0.13.0'],
|
|
['an array', []],
|
|
['an error object served with 200', { message: 'API rate limit exceeded' }],
|
|
['a non-string tag', { tag_name: 42 }],
|
|
['a tag that is not a version', { tag_name: 'nightly' }],
|
|
// The check only guarded the *start* of the tag, so anything beginning
|
|
// with a digit slipped through and was then compared as a version. A
|
|
// date-style tag reads as version 2024 and leaves every instance showing
|
|
// an update that does not exist, permanently.
|
|
['a date-style tag', { tag_name: '2024-01-05' }],
|
|
['a tag with a digit and then rubbish', { tag_name: '1abc' }],
|
|
])('returns null for %s', (_label, payload) => {
|
|
expect(parseLatestTag(payload)).toBeNull();
|
|
});
|
|
|
|
it('still accepts the shapes the project actually tags', () => {
|
|
expect(parseLatestTag({ tag_name: 'v0.13.0' })).toBe('v0.13.0');
|
|
expect(parseLatestTag({ tag_name: '0.13.0' })).toBe('0.13.0');
|
|
expect(parseLatestTag({ tag_name: 'v1.0' })).toBe('v1.0');
|
|
expect(parseLatestTag({ tag_name: 'v1.2.3-rc1' })).toBe('v1.2.3-rc1');
|
|
// Build metadata is ignorable for ordering, so rejecting it would mean
|
|
// never mentioning a release that is genuinely newer.
|
|
expect(parseLatestTag({ tag_name: 'v1.2.3+build.7' })).toBe('v1.2.3+build.7');
|
|
});
|
|
});
|