@wearesage/schema
Version:
A flexible schema definition and validation system for TypeScript with multi-database support
105 lines (83 loc) • 4 kB
text/typescript
import "reflect-metadata";
import {
MetadataRegistry,
SchemaBuilder
} from "../../core";
import { Neo4jAdapter } from "../../adapters/neo4j";
import { User } from "../../examples/blog/User";
import { Post } from "../../examples/blog/Post";
import { Tag } from "../../examples/blog/Tag";
// Add Neo4j-specific metadata for test
Reflect.defineMetadata("neo4j:label", "BlogUser", User);
Reflect.defineMetadata("neo4j:relationship", { type: "AUTHORED", direction: "OUT" }, User.prototype, "posts");
describe("Neo4jAdapter", () => {
let registry: MetadataRegistry;
let builder: SchemaBuilder;
let adapter: Neo4jAdapter;
beforeEach(() => {
// Set up registry, builder, and adapter for each test
registry = new MetadataRegistry();
builder = new SchemaBuilder(registry);
// Register entities
builder.registerEntities([User, Post, Tag]);
// Create adapter with mock connection
adapter = new Neo4jAdapter(registry, "bolt://localhost:7687");
});
test("should handle entities with custom Neo4j labels", async () => {
// We can indirectly verify the label handling through query operation
// which internally uses getNodeLabel
await adapter.query(User, { id: "test" });
// No assertions needed as we're just checking it doesn't throw
// We could use a spy on console.log to verify the label if needed
});
test("should initialize with connection string", () => {
// Create a new adapter with a different connection string
const testAdapter = new Neo4jAdapter(registry, "bolt://neo4j:7687");
// Just verify it was created successfully
expect(testAdapter).toBeInstanceOf(Neo4jAdapter);
});
test("should handle query operations with different criteria", async () => {
// Test querying by ID
const resultById = await adapter.query(User, { id: "user1" });
expect(resultById).toBeNull();
// Test querying by email
const resultByEmail = await adapter.query(User, { email: "test@example.com" });
expect(resultByEmail).toBeNull();
});
test("should handle relationship data in entity operations", () => {
// Verify that relationships are used in adapter operations through
// type-specific metadata, which we can't easily test directly
const metadata = Reflect.getMetadata("neo4j:relationship", User.prototype, "posts");
expect(metadata).toHaveProperty("type", "AUTHORED");
// This ensures the relationship metadata we're setting is correctly read
expect(metadata).toHaveProperty("direction", "OUT");
});
test("should support all required repository operations", async () => {
// Verify queryMany operation
const results = await adapter.queryMany(User, { active: true });
expect(Array.isArray(results)).toBe(true);
// Verify delete operation
await adapter.delete(User, "test123");
// No assertions needed here - just checking the operations don't throw
});
test("should handle query operations", async () => {
// Should not throw when querying by ID
await expect(adapter.query(User, { id: "test123" })).resolves.toBeNull();
// Should not throw when querying by criteria
await expect(adapter.query(User, { email: "test@example.com" })).resolves.toBeNull();
});
test("should handle queryMany operations", async () => {
// Should not throw when querying for multiple entities
await expect(adapter.queryMany(User, { active: true })).resolves.toEqual([]);
});
test("should handle delete operations", async () => {
// Should not throw when deleting an entity
await expect(adapter.delete(User, "user123")).resolves.not.toThrow();
});
test("should handle runNativeQuery operations", async () => {
// Should not throw when running a native query
const query = "MATCH (u:User) WHERE u.id = $id RETURN u";
const params = { id: "user123" };
await expect(adapter.runNativeQuery(query, params)).resolves.not.toThrow();
});
});