import { test } from 'node:test'; import assert from 'node:assert/strict'; import { describeUpdateError, manualDownloadUrl, MANUAL_DOWNLOAD_URL, parseUpdateError, } from './updateErrors'; test('parseUpdateError reads the native phase prefix', () => { assert.deepEqual(parseUpdateError('download: error sending request for url (x)', 'check'), { phase: 'download', message: 'error sending request for url (x)', }); assert.deepEqual(parseUpdateError('install: access denied', 'download'), { phase: 'install', message: 'access denied', }); }); test('parseUpdateError falls back to the caller phase for unprefixed errors', () => { assert.deepEqual(parseUpdateError('error sending request', 'check'), { phase: 'check', message: 'error sending request', }); }); test('the reported download failure reads as a busy server, not a failed check', () => { const { phase, message } = parseUpdateError( 'download: error sending request for url (https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/LotusChat-x86_64-setup.nsis.zip)', 'check', ); const text = describeUpdateError(phase, message); assert.match(text, /didn’t finish downloading/); assert.match(text, /download the installer yourself/); }); test('only signature failures are reported as a failed safety check', () => { assert.match( describeUpdateError('download', 'The signature X could not be decoded'), /safety check/, ); assert.doesNotMatch(describeUpdateError('download', 'No space left on device'), /safety/); }); test('check failures never suggest the app is broken', () => { assert.match(describeUpdateError('check', 'operation timed out'), /Lotus Chat still works/); assert.match(describeUpdateError('check', 'weird'), /Lotus Chat still works/); }); test('manual download link: Windows gets the installer, others the release page', () => { assert.equal( manualDownloadUrl('Mozilla/5.0 (Windows NT 10.0; Win64; x64) Edg/140'), MANUAL_DOWNLOAD_URL.windows, ); assert.equal(manualDownloadUrl('Mozilla/5.0 (X11; Linux x86_64)'), MANUAL_DOWNLOAD_URL.other); }); test('install kinds: anything unknown keeps the in-app updater', async () => { const { toInstallKind } = await import('./updateErrors'); assert.equal(toInstallKind('pacman'), 'pacman'); assert.equal(toInstallKind('deb'), 'deb'); assert.equal(toInstallKind('manual'), 'manual'); assert.equal(toInstallKind('in-app'), 'in-app'); assert.equal(toInstallKind(undefined), 'in-app', 'older desktop build without the command'); assert.equal(toInstallKind('rpm'), 'in-app'); }); test('package installs get their package manager’s command, not an Install button', async () => { const { packageUpdateHelp, isPackageManagedError } = await import('./updateErrors'); const pacman = packageUpdateHelp('pacman')!; // Not `pacman -U `: that also wants `.sig`, which we don't publish. assert.equal( pacman.command, 'curl -LO https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/LotusChat-x86_64.pkg.tar.zst && sudo pacman -U ./LotusChat-x86_64.pkg.tar.zst', ); assert.match(pacman.url, /LotusChat-x86_64\.pkg\.tar\.zst$/); const deb = packageUpdateHelp('deb')!; assert.match(deb.command!, /sudo apt install \.\/LotusChat-x86_64\.deb$/); assert.equal(packageUpdateHelp('manual')?.command, undefined); assert.equal(packageUpdateHelp('in-app'), undefined); assert.equal( isPackageManagedError('package-managed (pacman): update Lotus Chat with your package manager'), true, ); assert.equal( isPackageManagedError('Permission denied (os error 13) at path "/usr/bin/tauri_current_app"'), false, ); });