Files
awesome-opencode/test/compat.test.js
John SmithandClaude Opus 5.5 ef6357d8d1 feat(ci): required validate check with V2 probe, and pull_request_target triage
validate-pr.yml now runs on every PR (README-only PRs previously got no feedback), drops tj-actions/changed-files, runs unit tests, scripts/check-pr.js and a README/registry generation dry run, and supports workflow_dispatch so bot branches get the check. New plugin entries that are V1-only are blocked; declared compat must match what is detected. triage.yml labels PRs (ready, needs-v2, needs-metadata, needs-human, category) and keeps one results comment, using base-branch code only and reading PR files as data. The README workflow uses full history and Node 24.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 13:00:22 -04:00

55 lines
3.0 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const zlib = require('zlib');
const { manifestMarkers, sourceMarkers, tarFiles, verdict } = require('../scripts/utils/compat');
const detect = manifest => verdict([{ source: 'package.json', ...manifestMarkers(manifest) }]).compat;
test('V2 markers', () => {
assert.equal(detect({ dependencies: { '@opencode/plugin': '^2.0.0' } }), 'v2');
assert.equal(detect({ peerDependencies: { '@opencode/theme': '2.0.14' } }), 'v2');
assert.equal(detect({ devDependencies: { 'plugin-v2': 'npm:@opencode/[email protected]', '@opencode-ai/plugin': '1.18.25' } }), 'v2');
assert.equal(detect({ dependencies: { '@opencode-ai/plugin': '0.0.0-beta-18027' } }), 'v2');
assert.equal(detect({ dependencies: { '@opencode-ai/plugin': 'next' } }), 'v2');
assert.equal(detect({ dependencies: { '@opencode-ai/client': '0.0.0-next-17444' } }), 'v2');
});
test('V1 markers', () => {
assert.equal(detect({ dependencies: { '@opencode-ai/plugin': '^1.18.0' } }), 'v1');
assert.equal(detect({ dependencies: { '@opencode-ai/plugin': '*' } }), 'v1');
assert.equal(detect({ dependencies: { '@opencode-ai/sdk': '>=1.0.0' } }), 'v1');
});
test('no markers is unknown', () => {
assert.equal(detect({ dependencies: { zod: '^3' } }), 'unknown');
assert.equal(verdict([]).compat, 'unknown');
});
test('source markers', () => {
const v2 = sourceMarkers('import { Plugin } from "@opencode/plugin"\nexport default Plugin.define({ id: "x", async setup(ctx) {} })');
assert.deepEqual(v2.v2, ['@opencode/plugin']);
assert.equal(v2.define, true);
assert.equal(sourceMarkers('export const P = async ({ project, client, $, directory }) => ({})').v1Signature, true);
assert.equal(sourceMarkers('export const X = async () => ({\n "chat.params": async ({ model }, out) => {} })').v1Signature, true);
assert.equal(sourceMarkers('export const MAX = 1;').v1Signature, false);
assert.equal(sourceMarkers('const plugin = { id: PLAIN_ID, server: PlainPlugin, setup: setupPlain };').v2Signature, true);
assert.equal(sourceMarkers('export default { id: "x", async setup(ctx) { ctx.session.hook("prompt") } }').v2Signature, true);
assert.equal(sourceMarkers('export default { id: "obvious-grid", server: async (input) => ({ event }) }').v2Signature, false);
});
test('tarFiles reads regular files and strips the top folder', () => {
const header = (name, size, type = '0') => {
const h = Buffer.alloc(512);
h.write(name, 0);
h.write(size.toString(8).padStart(11, '0') + '\0', 124);
h.write(type, 156);
return h;
};
const body = Buffer.from('export default 1');
const padded = Buffer.concat([body, Buffer.alloc(512 - body.length)]);
const tar = Buffer.concat([header('owner-repo-sha/', 0, '5'), header('owner-repo-sha/src/index.ts', body.length), padded, Buffer.alloc(1024)]);
const files = [...tarFiles(zlib.gunzipSync(zlib.gzipSync(tar)))];
assert.deepEqual(files.map(f => f.name), ['src/index.ts']);
assert.equal(files[0].data.toString(), 'export default 1');
});