Some checks failed
Aduanasoft/PANEL_BASES_ANEXO24/pipeline/head There was a failure building this commit
Reviewed-on: #19 Co-authored-by: hreyes <hreyes@aduanasoft.com.mx> Co-committed-by: hreyes <hreyes@aduanasoft.com.mx>
204 lines
7.6 KiB
TypeScript
204 lines
7.6 KiB
TypeScript
/**
|
|
* Comparación de versiones y normalización de plataforma para CloudRestoreAS.
|
|
*
|
|
* Es la lógica que decide si a un servidor le falta actualizarse, así que los casos que se
|
|
* prueban son los que romperían eso en silencio: comparación lexicográfica (1.10 vs 1.9),
|
|
* versiones de distinta longitud, y valores no comparables.
|
|
*/
|
|
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
compareVersions,
|
|
effectiveArch,
|
|
effectivePlatform,
|
|
installPlatformVerdict,
|
|
isCrasPlatform,
|
|
isNewer,
|
|
isValidVersion,
|
|
osToPlatform,
|
|
parseVersion,
|
|
platformLabel,
|
|
DEFAULT_ARCH
|
|
} from './cras-version';
|
|
|
|
describe('isValidVersion', () => {
|
|
it('acepta versiones de puntos y números', () => {
|
|
for (const v of ['1', '1.0', '1.1.0', '26.7.1.4']) {
|
|
expect(isValidVersion(v), v).toBe(true);
|
|
}
|
|
});
|
|
|
|
it('rechaza lo que el PANEL no podría ordenar', () => {
|
|
for (const v of ['1.0.0-rc1', 'v1.0.0', '1.0.0a', '', ' ', 'latest', '1.2.3.4.5']) {
|
|
expect(isValidVersion(v), String(v)).toBe(false);
|
|
}
|
|
});
|
|
|
|
it('rechaza valores que no son cadena', () => {
|
|
expect(isValidVersion(null)).toBe(false);
|
|
expect(isValidVersion(undefined)).toBe(false);
|
|
expect(isValidVersion(110)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('parseVersion', () => {
|
|
it('descompone en enteros', () => {
|
|
expect(parseVersion('1.10.2')).toEqual([1, 10, 2]);
|
|
expect(parseVersion(' 2.0 ')).toEqual([2, 0]);
|
|
});
|
|
|
|
it('devuelve null si no es comparable', () => {
|
|
expect(parseVersion('1.0.0-rc1')).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('compareVersions', () => {
|
|
it('compara numéricamente, no como texto', () => {
|
|
// El error clásico: como cadenas, "1.9.0" > "1.10.0".
|
|
expect(compareVersions('1.10.0', '1.9.0')).toBe(1);
|
|
expect(compareVersions('1.9.0', '1.10.0')).toBe(-1);
|
|
});
|
|
|
|
it('rellena con ceros las de distinta longitud', () => {
|
|
expect(compareVersions('1.2', '1.2.0')).toBe(0);
|
|
expect(compareVersions('1.2.1', '1.2')).toBe(1);
|
|
expect(compareVersions('2', '1.9.9.9')).toBe(1);
|
|
});
|
|
|
|
it('es simétrica', () => {
|
|
expect(compareVersions('1.1.0', '1.1.0')).toBe(0);
|
|
expect(compareVersions('26.7.1.4', '26.7.1.3')).toBe(1);
|
|
expect(compareVersions('26.7.1.3', '26.7.1.4')).toBe(-1);
|
|
});
|
|
|
|
it('devuelve null cuando alguna no es comparable', () => {
|
|
expect(compareVersions('1.0.0-rc1', '1.0.0')).toBeNull();
|
|
expect(compareVersions('1.0.0', 'latest')).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('isNewer', () => {
|
|
it('detecta una versión más nueva', () => {
|
|
expect(isNewer('1.2.0', '1.1.0')).toBe(true);
|
|
expect(isNewer('1.10.0', '1.9.0')).toBe(true);
|
|
});
|
|
|
|
it('no ofrece downgrade ni reinstalación de la misma', () => {
|
|
expect(isNewer('1.1.0', '1.2.0')).toBe(false);
|
|
expect(isNewer('1.1.0', '1.1.0')).toBe(false);
|
|
});
|
|
|
|
it('sin versión instalada, hay algo que instalar', () => {
|
|
expect(isNewer('1.1.0', null)).toBe(true);
|
|
expect(isNewer('1.1.0', undefined)).toBe(true);
|
|
expect(isNewer('1.1.0', ' ')).toBe(true);
|
|
});
|
|
|
|
it('ante una versión no comparable prefiere NO ofrecer nada', () => {
|
|
// Preferible perderse una actualización que empujar un downgrade por un dato sucio.
|
|
expect(isNewer('1.0.0-rc1', '1.0.0')).toBe(false);
|
|
expect(isNewer('1.2.0', 'desconocida')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('osToPlatform', () => {
|
|
it('reconoce Windows en texto libre', () => {
|
|
for (const os of ['Windows Server 2019', 'windows 11', 'WIN SERVER 2022', 'Win']) {
|
|
expect(osToPlatform(os), os).toBe('windows');
|
|
}
|
|
});
|
|
|
|
it('reconoce distribuciones de Linux', () => {
|
|
for (const os of [
|
|
'Ubuntu 22.04',
|
|
'Debian 12',
|
|
'CentOS 7',
|
|
'RHEL 9',
|
|
'Red Hat Enterprise',
|
|
'Rocky Linux 9',
|
|
'AlmaLinux',
|
|
'SUSE',
|
|
'Oracle Linux 8'
|
|
]) {
|
|
expect(osToPlatform(os), os).toBe('linux');
|
|
}
|
|
});
|
|
|
|
it('devuelve null si no puede decidir, en lugar de adivinar', () => {
|
|
// Adivinar mandaría el binario equivocado; la UI pide elegir a mano.
|
|
for (const os of ['', ' ', null, undefined, 'servidor de la sucursal', 'macOS 14']) {
|
|
expect(osToPlatform(os as string), String(os)).toBeNull();
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('effectivePlatform', () => {
|
|
it('lo reportado por el agente manda sobre el texto libre', () => {
|
|
expect(effectivePlatform('linux', 'Windows Server 2019')).toBe('linux');
|
|
expect(effectivePlatform('windows', 'Ubuntu 22.04')).toBe('windows');
|
|
});
|
|
|
|
it('cae al texto libre cuando el agente no reportó', () => {
|
|
expect(effectivePlatform(null, 'Ubuntu 22.04')).toBe('linux');
|
|
expect(effectivePlatform(' ', 'Windows Server 2022')).toBe('windows');
|
|
});
|
|
|
|
it('ignora una plataforma reportada inválida', () => {
|
|
expect(effectivePlatform('solaris', 'Ubuntu 22.04')).toBe('linux');
|
|
expect(effectivePlatform('solaris', null)).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('effectiveArch', () => {
|
|
it('usa la reportada y normaliza a minúsculas', () => {
|
|
expect(effectiveArch('X86_64')).toBe('x86_64');
|
|
expect(effectiveArch('arm64')).toBe('arm64');
|
|
});
|
|
|
|
it('asume la única arquitectura que se publica hoy si falta', () => {
|
|
expect(effectiveArch(null)).toBe(DEFAULT_ARCH);
|
|
expect(effectiveArch(' ')).toBe(DEFAULT_ARCH);
|
|
});
|
|
});
|
|
|
|
describe('isCrasPlatform y platformLabel', () => {
|
|
it('valida el vocabulario del CHECK de cras_releases', () => {
|
|
expect(isCrasPlatform('windows')).toBe(true);
|
|
expect(isCrasPlatform('linux')).toBe(true);
|
|
expect(isCrasPlatform('solaris')).toBe(false);
|
|
expect(isCrasPlatform(null)).toBe(false);
|
|
});
|
|
|
|
it('etiqueta legible, incluso sin dato', () => {
|
|
expect(platformLabel('windows')).toBe('Windows');
|
|
expect(platformLabel('linux')).toBe('Linux');
|
|
expect(platformLabel(null)).toBe('Sin determinar');
|
|
});
|
|
});
|
|
|
|
describe('installPlatformVerdict', () => {
|
|
it('con plataforma conocida solo deja pasar el artefacto que corresponde', () => {
|
|
expect(installPlatformVerdict('linux', 'linux', null)).toBe('ok');
|
|
expect(installPlatformVerdict('windows', 'linux', null)).toBe('mismatch');
|
|
expect(installPlatformVerdict('linux', 'windows', null)).toBe('mismatch');
|
|
});
|
|
|
|
it('una confirmación no puede pasar por encima de una plataforma conocida', () => {
|
|
// El destino es Windows y el operador confirma "linux": sigue siendo un desajuste.
|
|
expect(installPlatformVerdict('windows', 'linux', 'linux')).toBe('mismatch');
|
|
});
|
|
|
|
it('sin plataforma determinada exige confirmación explícita del operador', () => {
|
|
// El defecto que se corrige: el modal preseleccionaba el primer artefacto del catálogo
|
|
// (el más recién descubierto, hoy Linux) para un servidor "Sin determinar".
|
|
expect(installPlatformVerdict(null, 'linux', null)).toBe('needs-ack');
|
|
expect(installPlatformVerdict(null, 'linux', '')).toBe('needs-ack');
|
|
expect(installPlatformVerdict(undefined, 'windows', undefined)).toBe('needs-ack');
|
|
});
|
|
|
|
it('la confirmación tiene que coincidir con la plataforma del artefacto', () => {
|
|
expect(installPlatformVerdict(null, 'linux', 'linux')).toBe('ok');
|
|
expect(installPlatformVerdict(null, 'linux', 'windows')).toBe('needs-ack');
|
|
expect(installPlatformVerdict(null, 'windows', ' WINDOWS ')).toBe('ok');
|
|
});
|
|
});
|