@wearesage/schema
Version:
A flexible schema definition and validation system for TypeScript with multi-database support
114 lines (92 loc) • 4.21 kB
text/typescript
import "reflect-metadata";
import {
MetadataRegistry,
SchemaBuilder
} from "../../core";
import { PostgreSQLAdapter } from "../../adapters/postgresql";
import { User } from "../../examples/blog/User";
import { Post } from "../../examples/blog/Post";
import { Tag } from "../../examples/blog/Tag";
// Add PostgreSQL-specific metadata for test
Reflect.defineMetadata("postgresql:table", "blog_users", User);
Reflect.defineMetadata(
"postgresql:relationship",
{ foreignKey: "user_id", joinTable: "user_posts" },
User.prototype,
"posts"
);
describe("PostgreSQLAdapter", () => {
let registry: MetadataRegistry;
let builder: SchemaBuilder;
let adapter: PostgreSQLAdapter;
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 string
adapter = new PostgreSQLAdapter(registry, "postgresql://localhost:5432/test");
});
test("should handle custom table names in queries", async () => {
// Execute a query that would internally call getTableName
await adapter.query(User, { id: "test" });
// No assertions needed as we're just checking it doesn't throw
// We could spy on console.log or internal methods if needed
});
test("should initialize with connection string", () => {
// Create a new adapter with a different connection string
const testAdapter = new PostgreSQLAdapter(registry, "postgresql://user:pass@localhost:5432/test");
// Just verify it was created successfully
expect(testAdapter).toBeInstanceOf(PostgreSQLAdapter);
});
test("should handle different query types and criteria", async () => {
// Query by ID
const resultById = await adapter.query(User, { id: "test123" });
expect(resultById).toBeNull();
// Query by email
const resultByEmail = await adapter.query(User, { email: "test@example.com" });
expect(resultByEmail).toBeNull();
// Query for multiple entities
const results = await adapter.queryMany(User, { active: true });
expect(Array.isArray(results)).toBe(true);
expect(results.length).toBe(0);
});
test("should handle relationship metadata in operations", () => {
// Check that the relationship metadata we set is correctly read
const metadata = Reflect.getMetadata("postgresql:relationship", User.prototype, "posts");
expect(metadata).toHaveProperty("foreignKey", "user_id");
expect(metadata).toHaveProperty("joinTable", "user_posts");
});
test("should expose database-specific operations", async () => {
// Run a native SQL query
const result = await adapter.runNativeQuery("SELECT * FROM users");
expect(result).toBeDefined();
// Delete operation should work without throwing
await adapter.delete(User, "test123");
});
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 = "SELECT * FROM users WHERE id = $1";
const params = ["user123"];
await expect(adapter.runNativeQuery(query, params)).resolves.not.toThrow();
});
test("should work with SQL query strings", () => {
// Just verify the adapter doesn't throw when executing a query
return expect(adapter.runNativeQuery("SELECT * FROM users")).resolves.not.toThrow();
});
});