Grafema Test Backend Usage
Problem
Tests querying the graph return malformed node data:
- IDs are internal numeric strings instead of human-readable semantic IDs
type field is undefined (only nodeType is set)
metadata is a raw JSON string instead of parsed object
originalId and other metadata fields are missing from node
Context / Trigger Conditions
-
Test uses backend.client to query nodes:
const graph = backend.client; // WRONG
const nodes = await collectNodes(graph.queryNodes({ type: 'net:request' }));
-
Node ID is numeric instead of semantic:
Expected: "net:request#__network__"
Actual: "52710336597754872375318185843222727675"
-
node.type is undefined but node.nodeType has the correct value
-
Using await graph.queryNodes() expecting an array (it's an async generator)
Solution
Issue 1: Use backend directly, not backend.client
// WRONG - returns unparsed wire format
const graph = backend.client;
// CORRECT - returns parsed nodes with human-readable IDs
const graph = backend;
Why: backend is RFDBServerBackend which has _parseNode() that:
- Extracts
originalId from metadata and uses it as the node's id
- Sets both
type and nodeType from wire format
- Parses and spreads metadata fields onto the node object
backend.client is the raw RFDBClient which returns the wire format without parsing.
Issue 2: Handle async generator properly
// WRONG - queryNodes returns async generator, not Promise<array>
const nodes = await graph.queryNodes({ type: 'net:request' });
nodes.length; // undefined - nodes is an async generator
// CORRECT - collect results into array
async function collectNodes(asyncGen) {
const results = [];
for await (const node of asyncGen) {
results.push(node);
}
return results;
}
const nodes = await collectNodes(graph.queryNodes({ type: 'net:request' }));
nodes.length; // works correctly
Issue 3: Use correct edge query methods
// WRONG - queryEdges doesn't exist
const edges = await graph.queryEdges({ type: 'CALLS', src: nodeId });
// CORRECT - use getOutgoingEdges or getIncomingEdges
const edges = await graph.getOutgoingEdges(nodeId, ['CALLS']);
Verification
After fixing, verify nodes have correct structure:
for await (const node of backend.queryNodes({ type: 'net:request' })) {
console.log('ID:', node.id); // Should be "net:request#__network__"
console.log('type:', node.type); // Should be "net:request"
console.log('nodeType:', node.nodeType); // Should be "net:request"
console.log('originalId:', node.originalId); // Should match id
}
Example
Full test pattern:
import { createTestBackend } from '../helpers/TestRFDB.js';
describe('My Test', () => {
let backend;
beforeEach(async () => {
backend = createTestBackend();
await backend.connect(); // Don't forget this!
});
afterEach(async () => {
if (backend) await backend.close();
});
it('should find nodes correctly', async () => {
// ... setup and analysis ...
// Use backend directly, not backend.client
const graph = backend;
// Collect async generator results
const nodes = [];
for await (const node of graph.queryNodes({ type: 'net:request' })) {
nodes.push(node);
}
// Now nodes is an array with properly parsed nodes
assert.strictEqual(nodes[0].id, 'net:request#__network__');
assert.strictEqual(nodes[0].type, 'net:request');
});
});
Notes
RFDBServerBackend._parseNode() is responsible for the transformation
- The
originalId is stored in the node's metadata JSON field in the database
- Both
type and nodeType are set to the same value after parsing
- Edge methods (
getOutgoingEdges, getIncomingEdges) return arrays, not generators
- Always call
backend.connect() in beforeEach - the backend is not auto-connected