Files
bare-operating-system/packages/bare-os-coreutils/test/appstore-pear.test.mjs
T
2026-08-18 18:11:34 -04:00

154 lines
4.2 KiB
JavaScript

import { readFile } from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import test from 'brittle'
import b4a from 'b4a'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
async function loadAppstoreBin() {
const runtime = await readFile(path.join(__dirname, '../lib/runtime.js'), 'utf8')
const p2p = await readFile(path.join(__dirname, '../lib/p2p/p2p-suite.js'), 'utf8')
const pear = await readFile(path.join(__dirname, '../lib/pear/appstore-pear.js'), 'utf8')
const body = await readFile(path.join(__dirname, '../src/appstore.js'), 'utf8')
return new AsyncFunction(
'ctx',
'argv',
`${runtime}\n${p2p}\n${pear}\n${body}\nif (typeof run === 'function') return await run(ctx, argv)\n`
)
}
function mkMemVfs(initial = {}) {
/** @type {Map<string, Uint8Array>} */
const files = new Map(Object.entries(initial))
return {
files,
async mkdir() {},
async readdir(p) {
const prefix = p.endsWith('/') ? p : p + '/'
const names = new Set()
for (const key of files.keys()) {
if (!key.startsWith(prefix)) continue
names.add(key.slice(prefix.length).split('/')[0])
}
return [...names].filter(Boolean)
},
async stat(p) {
if (!files.has(p)) {
for (const key of files.keys()) {
if (key.startsWith(p + '/')) return { isDirectory: true, type: 'directory' }
}
throw new Error('ENOENT')
}
return { isDirectory: false, type: 'file' }
},
async readFile(p) {
if (!files.has(p)) throw new Error('ENOENT ' + p)
return files.get(p)
},
async writeFile(p, buf) {
files.set(p, buf instanceof Uint8Array ? buf : new Uint8Array(buf))
}
}
}
test('appstore install fetches pear tree from local HDMS mount', async (t) => {
const key = '8wdec11bcygidig1qubkuexgfjw57we5whgcsbsajao73g9eagry'
const mount = '/mnt/pear-my-pear-app'
const home = '/home/guest'
const vfs = mkMemVfs({
[`${mount}/sources/index.js`]: b4a.from('console.log("Hello from my Pear app!");\n', 'utf8'),
[`${mount}/package.json`]: b4a.from(
JSON.stringify({ name: 'my-pear-app', main: 'index.js', version: '0.1.0' }),
'utf8'
)
})
const hdms = {
active: true,
byLabel: new Map([
[
'pear-my-pear-app',
{
drive: {},
entry: { label: 'pear-my-pear-app', key, mode: 'writable' }
}
]
]),
registry: { version: 1, drives: [{ label: 'pear-my-pear-app', key, mode: 'writable' }] }
}
const logs = []
const ctx = {
vfs,
b4a,
env: { HOME: home },
identity: { state: 'unlocked' },
disk: { hdmsController: hdms },
console: {
log(...a) {
logs.push(a.join(' '))
},
error() {},
warn() {}
}
}
const run = await loadAppstoreBin()
await run(ctx, [
'appstore',
'install',
'my-pear-app',
`pear://0.10.${key}`,
'--yes'
])
const pkgDir = `${home}/.appstore/packages/my-pear-app`
t.ok(vfs.files.has(`${pkgDir}/sources/index.js`))
t.ok(vfs.files.has(`${pkgDir}/manifest.json`))
t.ok(logs.some((l) => l.includes('fetched: 2 file')))
})
test('appstore launch runs materialized entry script', async (t) => {
const home = '/home/guest'
const pkgDir = `${home}/.appstore/packages/my-pear-app`
const vfs = mkMemVfs({
[`${home}/.appstore/registry.json`]: b4a.from(
JSON.stringify({
schema: 1,
packages: [
{
name: 'my-pear-app',
pearLink: 'pear://abc',
type: 'app'
}
]
}),
'utf8'
),
[`${pkgDir}/sources/index.js`]: b4a.from('console.log("Hello from my Pear app!");\n', 'utf8'),
[`${pkgDir}/package.json`]: b4a.from(JSON.stringify({ main: 'index.js' }), 'utf8')
})
const logs = []
const ctx = {
vfs,
b4a,
env: { HOME: home },
console: {
log(...a) {
logs.push(a.join(' '))
},
error() {},
warn() {}
}
}
const run = await loadAppstoreBin()
await run(ctx, ['appstore', 'launch', 'my-pear-app'])
t.ok(logs.some((l) => l.includes('Hello from my Pear app!')))
t.ok(logs.some((l) => l.includes('Launched "my-pear-app"')))
})