* fix: prevent bundled OpenCode self-upgrades * feat(vscode): support OpenCode upgrades * fix: refresh OpenCode update status on runtime switch --------- Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
259 lines
7.9 KiB
TypeScript
259 lines
7.9 KiB
TypeScript
import { describe, test, expect } from 'bun:test';
|
|
|
|
import {
|
|
resolveOpenCodeUpdateVersion,
|
|
resolveOpenCodeUpgradeStatusVersion,
|
|
shouldShowOpenCodeUpdateToast,
|
|
shouldShowPwaInstallToast,
|
|
} from '../openCodeUpdateDedup';
|
|
|
|
describe('shouldShowPwaInstallToast', () => {
|
|
test('returns true when nothing blocks the toast', () => {
|
|
expect(
|
|
shouldShowPwaInstallToast({
|
|
dismissed: null,
|
|
sessionShown: null,
|
|
hasActiveToast: false,
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
test('returns false when persistent dismissal is set', () => {
|
|
expect(
|
|
shouldShowPwaInstallToast({
|
|
dismissed: 'true',
|
|
sessionShown: null,
|
|
hasActiveToast: false,
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
|
|
test('returns false when the toast was already shown in this session', () => {
|
|
expect(
|
|
shouldShowPwaInstallToast({
|
|
dismissed: null,
|
|
sessionShown: 'true',
|
|
hasActiveToast: false,
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
|
|
test('returns false when the effect already owns an active toast', () => {
|
|
expect(
|
|
shouldShowPwaInstallToast({
|
|
dismissed: null,
|
|
sessionShown: null,
|
|
hasActiveToast: true,
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
|
|
test('treats non-"true" storage values as unset', () => {
|
|
expect(
|
|
shouldShowPwaInstallToast({
|
|
dismissed: 'false',
|
|
sessionShown: '0',
|
|
hasActiveToast: false,
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
test('persistent dismissal wins even when session marker is also set', () => {
|
|
expect(
|
|
shouldShowPwaInstallToast({
|
|
dismissed: 'true',
|
|
sessionShown: 'true',
|
|
hasActiveToast: false,
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('shouldShowOpenCodeUpdateToast', () => {
|
|
test('returns true for a fresh version with no dismissal and an empty seen set', () => {
|
|
expect(
|
|
shouldShowOpenCodeUpdateToast({
|
|
version: '1.16.0',
|
|
dismissedVersion: null,
|
|
seenVersions: new Set(),
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
test('returns false for an empty version string', () => {
|
|
expect(
|
|
shouldShowOpenCodeUpdateToast({
|
|
version: '',
|
|
dismissedVersion: null,
|
|
seenVersions: new Set(),
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
|
|
test('returns false when the version was already surfaced in this session', () => {
|
|
expect(
|
|
shouldShowOpenCodeUpdateToast({
|
|
version: '1.16.0',
|
|
dismissedVersion: null,
|
|
seenVersions: new Set(['1.16.0']),
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
|
|
test('returns false when the dismissed version matches the incoming version', () => {
|
|
expect(
|
|
shouldShowOpenCodeUpdateToast({
|
|
version: '1.16.0',
|
|
dismissedVersion: '1.16.0',
|
|
seenVersions: new Set(),
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
|
|
test('returns true when a different version was previously dismissed', () => {
|
|
expect(
|
|
shouldShowOpenCodeUpdateToast({
|
|
version: '1.17.0',
|
|
dismissedVersion: '1.16.0',
|
|
seenVersions: new Set(),
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
test('treats null dismissedVersion as no prior dismissal', () => {
|
|
expect(
|
|
shouldShowOpenCodeUpdateToast({
|
|
version: '1.16.0',
|
|
dismissedVersion: null,
|
|
seenVersions: new Set(['1.15.0']),
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
test('seen set blocks even when dismissed version differs', () => {
|
|
expect(
|
|
shouldShowOpenCodeUpdateToast({
|
|
version: '1.16.0',
|
|
dismissedVersion: '1.15.0',
|
|
seenVersions: new Set(['1.16.0']),
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('resolveOpenCodeUpdateVersion', () => {
|
|
test('returns the trimmed version when detail.version is a string', () => {
|
|
expect(resolveOpenCodeUpdateVersion({ version: '1.16.0' })).toBe('1.16.0');
|
|
});
|
|
|
|
test('trims surrounding whitespace from a string version', () => {
|
|
expect(resolveOpenCodeUpdateVersion({ version: ' 1.16.0 ' })).toBe('1.16.0');
|
|
});
|
|
|
|
test('returns empty string when detail is null', () => {
|
|
expect(resolveOpenCodeUpdateVersion(null)).toBe('');
|
|
});
|
|
|
|
test('returns empty string when detail is undefined', () => {
|
|
expect(resolveOpenCodeUpdateVersion(undefined)).toBe('');
|
|
});
|
|
|
|
test('returns empty string when detail is not an object', () => {
|
|
expect(resolveOpenCodeUpdateVersion('1.16.0')).toBe('');
|
|
expect(resolveOpenCodeUpdateVersion(42)).toBe('');
|
|
expect(resolveOpenCodeUpdateVersion(true)).toBe('');
|
|
});
|
|
|
|
test('returns empty string when the version field is missing', () => {
|
|
expect(resolveOpenCodeUpdateVersion({})).toBe('');
|
|
});
|
|
|
|
test('returns empty string when the version field is non-string', () => {
|
|
expect(resolveOpenCodeUpdateVersion({ version: 116 })).toBe('');
|
|
expect(resolveOpenCodeUpdateVersion({ version: null })).toBe('');
|
|
expect(resolveOpenCodeUpdateVersion({ version: { major: 1 } })).toBe('');
|
|
});
|
|
});
|
|
|
|
describe('resolveOpenCodeUpgradeStatusVersion', () => {
|
|
test('returns the trimmed latestVersion when available is true', () => {
|
|
expect(
|
|
resolveOpenCodeUpgradeStatusVersion({
|
|
available: true,
|
|
latestVersion: '1.16.0',
|
|
upgrade: { supported: true },
|
|
}),
|
|
).toBe('1.16.0');
|
|
});
|
|
|
|
test('trims surrounding whitespace from latestVersion', () => {
|
|
expect(
|
|
resolveOpenCodeUpgradeStatusVersion({
|
|
available: true,
|
|
latestVersion: ' 1.16.0 ',
|
|
upgrade: { supported: true },
|
|
}),
|
|
).toBe('1.16.0');
|
|
});
|
|
|
|
test('returns empty string when status is null', () => {
|
|
expect(resolveOpenCodeUpgradeStatusVersion(null)).toBe('');
|
|
});
|
|
|
|
test('returns empty string when status is undefined', () => {
|
|
expect(resolveOpenCodeUpgradeStatusVersion(undefined)).toBe('');
|
|
});
|
|
|
|
test('returns empty string when available is false', () => {
|
|
expect(
|
|
resolveOpenCodeUpgradeStatusVersion({
|
|
available: false,
|
|
latestVersion: '1.16.0',
|
|
}),
|
|
).toBe('');
|
|
});
|
|
|
|
test('fails closed when the server does not explicitly support upgrades', () => {
|
|
expect(
|
|
resolveOpenCodeUpgradeStatusVersion({
|
|
available: true,
|
|
latestVersion: '1.16.0',
|
|
}),
|
|
).toBe('');
|
|
expect(
|
|
resolveOpenCodeUpgradeStatusVersion({
|
|
available: true,
|
|
latestVersion: '1.16.0',
|
|
upgrade: { supported: false },
|
|
}),
|
|
).toBe('');
|
|
});
|
|
|
|
test('returns empty string when available is missing or null', () => {
|
|
expect(
|
|
resolveOpenCodeUpgradeStatusVersion({
|
|
latestVersion: '1.16.0',
|
|
}),
|
|
).toBe('');
|
|
expect(
|
|
resolveOpenCodeUpgradeStatusVersion({
|
|
available: null,
|
|
latestVersion: '1.16.0',
|
|
}),
|
|
).toBe('');
|
|
});
|
|
|
|
test('returns empty string when latestVersion is missing', () => {
|
|
expect(resolveOpenCodeUpgradeStatusVersion({ available: true })).toBe('');
|
|
});
|
|
|
|
test('returns empty string when latestVersion is non-string', () => {
|
|
expect(
|
|
resolveOpenCodeUpgradeStatusVersion({
|
|
available: true,
|
|
latestVersion: null,
|
|
}),
|
|
).toBe('');
|
|
});
|
|
});
|