#!/bin/sh
# The upstream suite in debian/tests/node exercises the loader itself.  What it
# never touches is the rest of the installed tree: the four plugin bundles are
# shipped but nothing loads them.  So: check the loader's API surface, then run
# each plugin bundle the way the AMD loader does (a function taking require and
# define) and look at what it registered.
set -eu

SHARE=${VL_SHARE:-/usr/share/nodejs/vscode-loader}
T=$(mktemp -d)
trap 'rm -rf "$T"' EXIT

cat >"$T/check.cjs" <<'EOF'
'use strict';
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');

const SHARE = process.env.VL_SHARE || '/usr/share/nodejs/vscode-loader';
const loader = require(path.join(SHARE, 'src/loader.js'));

assert.equal(typeof loader, 'function', 'loader.js does not export a function');
for (const m of ['config', 'getConfig', 'reset', 'define', 'getStats', 'getBuildInfo']) {
	assert.equal(typeof loader[m], 'function', 'loader.' + m + ' is missing');
}

// The loader evaluates a module as a function of (require, define, __filename,
// __dirname); the plugins call define(id, plugin) at the end.  Do the same, with
// a define that records the registration and a require that also offers
// nodeRequire, which the build flavours use for fs.
function registration(file) {
	const full = path.join(SHARE, 'src', file);
	const source = fs.readFileSync(full, 'utf8');
	let got = null;
	const nodeRequire = (id) => require(id);
	nodeRequire.nodeRequire = nodeRequire;
	const define = (id, value) => { got = { id, value }; };
	new Function('require', 'define', '__filename', '__dirname', source)
		.call({}, nodeRequire, define, full, path.dirname(full));
	assert.ok(got, file + ' registered no module');
	return got;
}

const expected = {
	'css.js': { id: 'vs/css', methods: ['load'] },
	'css.build.js': { id: 'vs/css', methods: ['load', 'write'] },
	'nls.js': { id: 'vs/nls', methods: ['load', 'create'] },
	'nls.build.js': { id: 'vs/nls', methods: ['load', 'write', 'finishBuild'] },
};

for (const [file, want] of Object.entries(expected)) {
	const got = registration(file);
	assert.equal(got.id, want.id, file + ' registered as ' + got.id);
	for (const m of want.methods) {
		assert.equal(typeof got.value[m], 'function', file + ': the plugin has no ' + m + '()');
	}
}

console.log('tree: ok');
EOF

VL_SHARE="$SHARE" node "$T/check.cjs"
