moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

View File

@@ -0,0 +1,263 @@
import { describe, it, expect } from 'vitest';
import path from 'node:path';
import { writeFileSync, mkdirSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import {
getDefaultInstallerConfig,
generateNsisDefines,
validateInstallPath,
isSystemPath,
getUninstallPrompt,
getVersionFromPackage,
} from './installer-config.js';
// ─── getDefaultInstallerConfig ──────────────────────────────────────────────
describe('getDefaultInstallerConfig', () => {
it('returns a valid config with expected defaults', () => {
const config = getDefaultInstallerConfig();
expect(config.productName).toBe('Waggle');
expect(config.version).toBe('0.1.0');
expect(config.publisher).toBe('Waggle');
expect(config.defaultInstallDir).toBe('C:\\Program Files\\Waggle');
expect(config.dataDir).toBe('~/.waggle');
expect(config.autostart).toBe(true);
expect(config.desktopShortcut).toBe(true);
expect(config.startMenuEntry).toBe(true);
expect(config.launchAfterInstall).toBe(true);
});
it('returns a new object each time', () => {
const a = getDefaultInstallerConfig();
const b = getDefaultInstallerConfig();
expect(a).toEqual(b);
expect(a).not.toBe(b);
});
});
// ─── generateNsisDefines ───────────────────────────────────────────────────
describe('generateNsisDefines', () => {
it('maps all config fields to NSIS defines', () => {
const config = getDefaultInstallerConfig();
const defines = generateNsisDefines(config);
expect(defines.PRODUCT_NAME).toBe('Waggle');
expect(defines.PRODUCT_VERSION).toBe('0.1.0');
expect(defines.PRODUCT_PUBLISHER).toBe('Waggle');
expect(defines.DEFAULT_INSTALL_DIR).toBe('C:\\Program Files\\Waggle');
expect(defines.DATA_DIR).toBe('~/.waggle');
expect(defines.AUTOSTART).toBe('1');
expect(defines.DESKTOP_SHORTCUT).toBe('1');
expect(defines.START_MENU_ENTRY).toBe('1');
expect(defines.LAUNCH_AFTER_INSTALL).toBe('1');
});
it('sets boolean defines to "0" when disabled', () => {
const config = getDefaultInstallerConfig();
config.autostart = false;
config.desktopShortcut = false;
config.startMenuEntry = false;
config.launchAfterInstall = false;
const defines = generateNsisDefines(config);
expect(defines.AUTOSTART).toBe('0');
expect(defines.DESKTOP_SHORTCUT).toBe('0');
expect(defines.START_MENU_ENTRY).toBe('0');
expect(defines.LAUNCH_AFTER_INSTALL).toBe('0');
});
it('handles custom product names and versions', () => {
const config = getDefaultInstallerConfig();
config.productName = 'Waggle Pro';
config.version = '2.5.0';
const defines = generateNsisDefines(config);
expect(defines.PRODUCT_NAME).toBe('Waggle Pro');
expect(defines.PRODUCT_VERSION).toBe('2.5.0');
});
});
// ─── validateInstallPath ────────────────────────────────────────────────────
describe('validateInstallPath', () => {
it('accepts a standard Program Files path', () => {
const result = validateInstallPath('C:\\Program Files\\Waggle');
expect(result.valid).toBe(true);
expect(result.error).toBeUndefined();
});
it('accepts a custom install path', () => {
const result = validateInstallPath('D:\\Apps\\Waggle');
expect(result.valid).toBe(true);
});
it('accepts forward slashes', () => {
const result = validateInstallPath('C:/Users/test/Waggle');
expect(result.valid).toBe(true);
});
it('accepts UNC paths', () => {
const result = validateInstallPath('\\\\server\\share\\Waggle');
expect(result.valid).toBe(true);
});
it('rejects empty path', () => {
const result = validateInstallPath('');
expect(result.valid).toBe(false);
expect(result.error).toContain('empty');
});
it('rejects whitespace-only path', () => {
const result = validateInstallPath(' ');
expect(result.valid).toBe(false);
expect(result.error).toContain('empty');
});
it('rejects relative paths', () => {
const result = validateInstallPath('Waggle\\bin');
expect(result.valid).toBe(false);
expect(result.error).toContain('absolute');
});
it('rejects paths with invalid characters', () => {
const result = validateInstallPath('C:\\Program Files\\Waggle<test>');
expect(result.valid).toBe(false);
expect(result.error).toContain('invalid characters');
});
it('rejects paths that are too long', () => {
const longPath = 'C:\\' + 'a'.repeat(250);
const result = validateInstallPath(longPath);
expect(result.valid).toBe(false);
expect(result.error).toContain('too long');
});
it('rejects bare drive root', () => {
const result = validateInstallPath('C:\\');
expect(result.valid).toBe(false);
expect(result.error).toContain('drive root');
});
it('rejects drive letter without backslash', () => {
const result = validateInstallPath('C:');
expect(result.valid).toBe(false);
expect(result.error).toBeDefined();
});
});
// ─── isSystemPath ───────────────────────────────────────────────────────────
describe('isSystemPath', () => {
it('detects Program Files', () => {
expect(isSystemPath('C:\\Program Files\\Waggle')).toBe(true);
});
it('detects Program Files (x86)', () => {
expect(isSystemPath('C:\\Program Files (x86)\\Waggle')).toBe(true);
});
it('detects Windows directory', () => {
expect(isSystemPath('C:\\Windows\\System32')).toBe(true);
});
it('detects ProgramData', () => {
expect(isSystemPath('C:\\ProgramData\\Waggle')).toBe(true);
});
it('is case-insensitive', () => {
expect(isSystemPath('c:\\program files\\waggle')).toBe(true);
expect(isSystemPath('C:\\PROGRAM FILES\\Waggle')).toBe(true);
});
it('handles forward slashes', () => {
expect(isSystemPath('C:/Program Files/Waggle')).toBe(true);
});
it('returns false for user directories', () => {
expect(isSystemPath('C:\\Users\\test\\Waggle')).toBe(false);
});
it('returns false for custom paths', () => {
expect(isSystemPath('D:\\Apps\\Waggle')).toBe(false);
});
});
// ─── getUninstallPrompt ─────────────────────────────────────────────────────
describe('getUninstallPrompt', () => {
it('includes the data directory in the prompt', () => {
const prompt = getUninstallPrompt('~/.waggle');
expect(prompt).toContain('~/.waggle');
});
it('mentions keeping data for future use', () => {
const prompt = getUninstallPrompt('C:\\Users\\test\\.waggle');
expect(prompt).toContain('keep it for future use');
});
it('mentions deleting all data option', () => {
const prompt = getUninstallPrompt('~/.waggle');
expect(prompt).toContain('delete all data');
});
it('mentions agents and memories', () => {
const prompt = getUninstallPrompt('~/.waggle');
expect(prompt).toContain('agents');
expect(prompt).toContain('memories');
});
});
// ─── getVersionFromPackage ──────────────────────────────────────────────────
describe('getVersionFromPackage', () => {
const tmpDir = path.join(tmpdir(), 'waggle-installer-test-' + Date.now());
// Setup / teardown
const setup = () => mkdirSync(tmpDir, { recursive: true });
const cleanup = () => rmSync(tmpDir, { recursive: true, force: true });
it('reads the version from a valid package.json', () => {
setup();
try {
const pkgPath = path.join(tmpDir, 'package.json');
writeFileSync(pkgPath, JSON.stringify({ name: 'test', version: '1.2.3' }));
expect(getVersionFromPackage(pkgPath)).toBe('1.2.3');
} finally {
cleanup();
}
});
it('throws for package.json without version', () => {
setup();
try {
const pkgPath = path.join(tmpDir, 'package.json');
writeFileSync(pkgPath, JSON.stringify({ name: 'test' }));
expect(() => getVersionFromPackage(pkgPath)).toThrow('No valid "version"');
} finally {
cleanup();
}
});
it('throws for non-existent file', () => {
expect(() => getVersionFromPackage('/nonexistent/package.json')).toThrow();
});
it('reads the actual app package.json version', () => {
const appPkgPath = path.resolve(__dirname, '..', 'package.json');
const version = getVersionFromPackage(appPkgPath);
expect(version).toMatch(/^\d+\.\d+\.\d+/);
});
it('throws with a descriptive error for malformed JSON', () => {
setup();
try {
const pkgPath = path.join(tmpDir, 'bad.json');
writeFileSync(pkgPath, '{ not valid json!!!');
expect(() => getVersionFromPackage(pkgPath)).toThrow('Failed to parse');
} finally {
cleanup();
}
});
});