Files
poshmanager/server/test/recipes.test.mjs
2026-08-09 17:33:11 -05:00

93 lines
4.2 KiB
JavaScript

import './setup.mjs';
import test from 'node:test';
import assert from 'node:assert/strict';
import { load } from './setup.mjs';
const { listRecipes, searchRecipes, getRecipe, buildRecipeArtifacts } =
await load('../services/recipeService.js');
// --- catalog -----------------------------------------------------------------
test('listRecipes exposes a sanitized catalog with the fields the UI needs', () => {
const list = listRecipes();
assert.ok(list.length >= 10, 'catalog has a useful number of recipes');
const chrome = list.find((r) => r.id === 'google-chrome');
assert.ok(chrome);
assert.equal(chrome.wingetId, 'Google.Chrome');
assert.ok(chrome.installArgs.includes('/qn'));
assert.ok(chrome.homepage.startsWith('https://'));
});
test('every recipe references a known installer technology and a valid detection footprint', async () => {
const { listInstallerTechnologies } = await load('../services/installerIntelService.js');
const techIds = new Set(listInstallerTechnologies().map((t) => t.id));
for (const r of listRecipes()) {
assert.ok(techIds.has(r.installerType), `${r.id} -> ${r.installerType} is a known technology`);
// Detection must not throw when applied (file/registry/msi all valid here).
assert.doesNotThrow(() => buildRecipeArtifacts(getRecipe(r.id)), `${r.id} detection builds`);
}
});
test('enterprise agents without a winget id still build, but skip the catalog app', () => {
const falcon = getRecipe('crowdstrike-falcon');
assert.equal(falcon.wingetId, '');
const { application, deployment } = buildRecipeArtifacts(falcon);
assert.equal(application, null, 'no winget id -> no auto-tracked app');
assert.ok(deployment.detectionRule.includes('CSFalconService.exe'));
});
test('searchRecipes matches vendor, name, and winget id case-insensitively', () => {
assert.ok(searchRecipes('mozilla').some((r) => r.id === 'mozilla-firefox'));
assert.ok(searchRecipes('VLC').some((r) => r.id === 'vlc'));
assert.ok(searchRecipes('Microsoft.PowerShell').some((r) => r.id === 'powershell-7'));
assert.equal(searchRecipes('nonexistent-app-xyz').length, 0);
assert.equal(searchRecipes('').length, listRecipes().length);
});
// --- apply transform (pure) --------------------------------------------------
test('buildRecipeArtifacts produces profile + deployment + tracked app for an MSI recipe', () => {
const { profile, deployment, application } = buildRecipeArtifacts(getRecipe('google-chrome'));
// Profile carries the raw silent install as a PSADT install task.
assert.equal(profile.name, 'Google Chrome');
assert.equal(profile.appVendor, 'Google');
assert.equal(profile.installTasks.length, 1);
assert.equal(profile.installTasks[0].type, 'msi');
assert.equal(profile.installTasks[0].filePath, 'googlechromestandaloneenterprise64.msi');
assert.ok(profile.installTasks[0].arguments.includes('/qn'));
// Deployment wraps it in PSADT v4 with a file-detection rule.
assert.equal(deployment.commandStyle, 'v4');
assert.equal(deployment.detectionType, 'custom-script');
assert.ok(deployment.detectionRule.includes('chrome.exe'));
assert.equal(deployment.status, 'draft');
// Catalog app is wired to the winget version watcher.
assert.equal(application.versionSource, 'winget');
assert.equal(application.versionSourceRef, 'Google.Chrome');
assert.equal(application.autoCheck, true);
});
test('EXE-based recipes become exe install tasks with the silent switch', () => {
const { profile } = buildRecipeArtifacts(getRecipe('git'));
assert.equal(profile.installTasks[0].type, 'exe');
assert.ok(profile.installTasks[0].arguments.includes('/VERYSILENT'));
});
test('applying with group visibility scopes the group id', () => {
const { profile, deployment } = buildRecipeArtifacts(getRecipe('7zip'), { visibility: 'group', groupId: 'grp_1' });
assert.equal(profile.visibility, 'group');
assert.equal(profile.groupId, 'grp_1');
assert.equal(deployment.groupId, 'grp_1');
});
test('group id is dropped when visibility is not group', () => {
const { profile } = buildRecipeArtifacts(getRecipe('7zip'), { visibility: 'personal', groupId: 'grp_1' });
assert.equal(profile.groupId, null);
});
test('buildRecipeArtifacts throws on a missing recipe', () => {
assert.throws(() => buildRecipeArtifacts(null));
});