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

68 lines
3.2 KiB
JavaScript

import './setup.mjs';
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { adminUserId, load } from './setup.mjs';
const owner = adminUserId();
const { createPsadtProfile, renderPsadtProfile } = await load('../models/psadtModel.js');
const { createAssetFromUpload, createAssetLink, listLinkedAssets } = await load('../models/assetModel.js');
const { buildZip, planPackageLayout } = await load('../services/packageBuilder.js');
function seedAsset(name, contents) {
const tmp = path.join(os.tmpdir(), `pkg-src-${Math.random().toString(16).slice(2)}`);
fs.writeFileSync(tmp, contents);
return createAssetFromUpload(
{ path: tmp, originalname: name, mimetype: 'application/octet-stream', size: contents.length },
{ name, visibility: 'shared' },
owner
);
}
test('listLinkedAssets returns a PSADT profile\'s linked assets with their package path and role', () => {
const profile = createPsadtProfile({ name: 'Linked Pkg App', appVendor: 'Acme', appName: 'Tool', visibility: 'shared' }, owner);
const installer = seedAsset('setup.exe', Buffer.from('MZ binary'));
createAssetLink(installer.id, { targetType: 'psadt_profile', targetId: profile.id, linkRole: 'installer', packagePath: 'Files/setup.exe' }, owner);
const linked = listLinkedAssets('psadt_profile', profile.id, owner);
assert.equal(linked.length, 1);
assert.equal(linked[0].assetId, installer.id);
assert.equal(linked[0].linkRole, 'installer');
assert.equal(linked[0].packagePath, 'Files/setup.exe');
});
test('a profile + linked assets assemble into a zip carrying the rendered script and payload', () => {
const profile = createPsadtProfile({ name: 'Assemble App', appVendor: 'Acme', appName: 'Assemble', visibility: 'shared' }, owner);
const installer = seedAsset('install.exe', Buffer.from('payload-bytes'));
const config = seedAsset('settings.xml', Buffer.from('<config/>'));
createAssetLink(installer.id, { targetType: 'psadt_profile', targetId: profile.id, linkRole: 'installer' }, owner);
createAssetLink(config.id, { targetType: 'psadt_profile', targetId: profile.id, linkRole: 'support-file' }, owner);
const rendered = renderPsadtProfile(profile.id, owner);
const layout = planPackageLayout(listLinkedAssets('psadt_profile', profile.id, owner));
assert.deepEqual(layout.assets.map((a) => a.packagePath).sort(), ['Files/install.exe', 'SupportFiles/settings.xml']);
const zip = buildZip([
{ path: 'Invoke-AppDeployToolkit.ps1', data: Buffer.from(rendered.script, 'utf8') },
{ path: 'Files/install.exe', data: Buffer.from('payload-bytes') }
]);
const names = listZipNames(zip);
assert.ok(names.includes('Invoke-AppDeployToolkit.ps1'));
assert.ok(names.includes('Files/install.exe'));
});
function listZipNames(buf) {
const names = [];
let pos = 0;
while (buf.readUInt32LE(pos) === 0x04034b50) {
const compSize = buf.readUInt32LE(pos + 18);
const nameLen = buf.readUInt16LE(pos + 26);
const extraLen = buf.readUInt16LE(pos + 28);
names.push(buf.slice(pos + 30, pos + 30 + nameLen).toString('utf8'));
pos = pos + 30 + nameLen + extraLen + compSize;
}
return names;
}