qwen_2.5_model / src /engine /engine-parity.spec.ts
Muhammad Noman
Deploy OpenWA to Hugging Face Spaces
46252cd
Raw
History Blame Contribute Delete
3.39 kB
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { BaileysAdapter } from './adapters/baileys.adapter';
import { WhatsAppWebJsAdapter } from './adapters/whatsapp-web-js.adapter';
import { ENGINE_CAPABILITY_MATRIX } from './engine-capability-matrix';
/**
* Drift invariants for the engine capability matrix. The matrix's `status` (supported /
* not-available) is hand-curated and richer than a throw-scan: it also marks "phantom support"
* methods (adapter stubs that return null/[] without throwing β€” see docs/engine-capability-matrix.md).
* So the gate asserts the invariants a throw-scan CAN verify, not full equality:
*
* 1. A method whose adapter body throws EngineNotSupportedError/ChannelMediaNotSupportedError
* MUST be `not-available` in the matrix (throws always mean unavailable).
* 2. A method the matrix marks `supported` MUST NOT throw.
*
* The allowed gap (not deliberate drift): a method that is `not-available` but does not throw today
* β€” a phantom stub. Those are hand-tracked in the matrix; a throw-scan cannot see them. If an adapter
* method starts or stops throwing, one of the invariants trips and forces a deliberate matrix update.
*
* No engine is instantiated and no Chromium/socket is opened: it reads method bodies via
* `Class.prototype.method.toString()`, a fast hermetic structural check.
*/
const UNSUPPORTED_RE = /this\.unsupported\(|EngineNotSupportedError|ChannelMediaNotSupportedError/;
function readInterfaceMethods(): string[] {
const src = readFileSync(join(__dirname, 'interfaces', 'whatsapp-engine.interface.ts'), 'utf8');
const names = new Set<string>();
for (const line of src.split('\n')) {
const match = line.match(/^\s{2}([a-zA-Z][a-zA-Z0-9]*)\s*\(/);
if (match) names.add(match[1]);
}
return [...names].sort();
}
type AdapterCtor = { prototype: Record<string, unknown> };
type AdapterKey = 'wwjs' | 'baileys';
const ADAPTERS: ReadonlyArray<[AdapterKey, AdapterCtor]> = [
['wwjs', WhatsAppWebJsAdapter as unknown as AdapterCtor],
['baileys', BaileysAdapter as unknown as AdapterCtor],
];
function liveThrows(adapter: AdapterCtor, method: string): boolean {
const fn = adapter.prototype[method];
if (typeof fn !== 'function') return true; // missing method = effectively unavailable
return UNSUPPORTED_RE.test(String(fn));
}
describe('engine capability matrix β€” drift invariants', () => {
const methods = readInterfaceMethods();
const matrixKeys = Object.keys(ENGINE_CAPABILITY_MATRIX).sort();
it('matrix keys exactly match the interface methods (no missing, no stale)', () => {
const missing = methods.filter(m => !(m in ENGINE_CAPABILITY_MATRIX));
const stale = matrixKeys.filter(k => !methods.includes(k));
expect({ missing, stale }).toEqual({ missing: [], stale: [] });
});
it.each(methods)('%s: throws β‡’ not-available, supported β‡’ not-throws', method => {
const entry = ENGINE_CAPABILITY_MATRIX[method];
for (const [adapter, ctor] of ADAPTERS) {
const throws = liveThrows(ctor, method);
const status = entry[adapter].status;
if (throws) {
expect({ method, adapter, status }).toEqual({ method, adapter, status: 'not-available' });
}
if (status === 'supported') {
expect({ method, adapter, throws }).toEqual({ method, adapter, throws: false });
}
}
});
});