Skip to main content
Glama
DatabaseSchema.test.ts9.11 kB
import { describe, it, expect, beforeEach } from 'vitest'; import { Environment } from '../value-objects/Environment'; import { Column } from './Column'; import { ForeignKey } from './ForeignKey'; import { DatabaseSchema } from './DatabaseSchema'; import { TableInfo } from './TableInfo'; describe('DatabaseSchema', () => { let testDate: Date; let usersTable: TableInfo; let postsTable: TableInfo; beforeEach(() => { testDate = new Date('2025-01-01T12:00:00Z'); usersTable = new TableInfo( 'users', 'table', [new Column('id', 'INTEGER', true), new Column('name', 'TEXT')] ); postsTable = new TableInfo( 'posts', 'table', [ new Column('id', 'INTEGER', true), new Column('user_id', 'INTEGER'), new Column('title', 'TEXT'), ], [], [new ForeignKey('posts', 'user_id', 'users', 'id', 'CASCADE')] ); }); describe('constructor', () => { it('should create schema with all properties', () => { const schema = new DatabaseSchema( 'my_database', Environment.DEVELOPMENT, [usersTable, postsTable], testDate ); expect(schema.name).toBe('my_database'); expect(schema.environment).toBe(Environment.DEVELOPMENT); expect(schema.tables.length).toBe(2); expect(schema.fetchedAt).toBe(testDate); }); it('should trim database name', () => { const schema = new DatabaseSchema( ' my_database ', Environment.PRODUCTION, [usersTable], testDate ); expect(schema.name).toBe('my_database'); }); it('should throw error for empty database name', () => { expect( () => new DatabaseSchema('', Environment.DEVELOPMENT, [usersTable], testDate) ).toThrow('Database name cannot be empty'); }); it('should throw error for empty tables array', () => { expect(() => new DatabaseSchema('db', Environment.DEVELOPMENT, [], testDate)).toThrow( 'Database must have at least one table' ); }); it('should be immutable', () => { const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable], testDate); expect(Object.isFrozen(schema)).toBe(true); expect(Object.isFrozen(schema.tables)).toBe(true); }); }); describe('getTable()', () => { it('should return table by name', () => { const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable], testDate); const table = schema.getTable('users'); expect(table).toBeDefined(); expect(table?.name).toBe('users'); }); it('should return undefined for non-existent table', () => { const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable], testDate); expect(schema.getTable('nonexistent')).toBeUndefined(); }); }); describe('getTablesThatReference()', () => { it('should return tables that reference specified table', () => { const schema = new DatabaseSchema( 'db', Environment.DEVELOPMENT, [usersTable, postsTable], testDate ); const referencingTables = schema.getTablesThatReference('users'); expect(referencingTables.length).toBe(1); expect(referencingTables[0].name).toBe('posts'); }); it('should return empty array when no tables reference specified table', () => { const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable], testDate); const referencingTables = schema.getTablesThatReference('users'); expect(referencingTables).toEqual([]); }); }); describe('getTablesReferencedBy()', () => { it('should return tables referenced by specified table', () => { const schema = new DatabaseSchema( 'db', Environment.DEVELOPMENT, [usersTable, postsTable], testDate ); const referenced = schema.getTablesReferencedBy('posts'); expect(referenced).toEqual(['users']); }); it('should return empty array when table has no references', () => { const schema = new DatabaseSchema( 'db', Environment.DEVELOPMENT, [usersTable, postsTable], testDate ); const referenced = schema.getTablesReferencedBy('users'); expect(referenced).toEqual([]); }); it('should return empty array for non-existent table', () => { const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable], testDate); const referenced = schema.getTablesReferencedBy('nonexistent'); expect(referenced).toEqual([]); }); }); describe('getTableCount()', () => { it('should return table count', () => { const schema = new DatabaseSchema( 'db', Environment.DEVELOPMENT, [usersTable, postsTable], testDate ); expect(schema.getTableCount()).toBe(2); }); }); describe('getTablesWithoutPrimaryKey()', () => { it('should return tables without primary keys', () => { const noPkTable = new TableInfo('logs', 'table', [new Column('message', 'TEXT')]); const schema = new DatabaseSchema( 'db', Environment.DEVELOPMENT, [usersTable, noPkTable], testDate ); const tables = schema.getTablesWithoutPrimaryKey(); expect(tables.length).toBe(1); expect(tables[0].name).toBe('logs'); }); it('should return empty array when all tables have primary keys', () => { const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable], testDate); expect(schema.getTablesWithoutPrimaryKey()).toEqual([]); }); }); describe('getTablesWithForeignKeys()', () => { it('should return tables with foreign keys', () => { const schema = new DatabaseSchema( 'db', Environment.DEVELOPMENT, [usersTable, postsTable], testDate ); const tables = schema.getTablesWithForeignKeys(); expect(tables.length).toBe(1); expect(tables[0].name).toBe('posts'); }); it('should return empty array when no tables have foreign keys', () => { const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable], testDate); expect(schema.getTablesWithForeignKeys()).toEqual([]); }); }); describe('getViews()', () => { it('should return all views', () => { const view = new TableInfo('user_view', 'view', [new Column('id', 'INTEGER')]); const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable, view], testDate); const views = schema.getViews(); expect(views.length).toBe(1); expect(views[0].name).toBe('user_view'); }); it('should return empty array when no views', () => { const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable], testDate); expect(schema.getViews()).toEqual([]); }); }); describe('getBaseTables()', () => { it('should return all base tables (non-views)', () => { const view = new TableInfo('user_view', 'view', [new Column('id', 'INTEGER')]); const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable, view], testDate); const tables = schema.getBaseTables(); expect(tables.length).toBe(1); expect(tables[0].name).toBe('users'); }); }); describe('isFresh()', () => { it('should return true for freshly fetched schema', () => { const now = new Date(); const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable], now); expect(schema.isFresh(10)).toBe(true); }); it('should return false for stale schema', () => { const old = new Date(Date.now() - 15 * 60 * 1000); // 15 minutes ago const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable], old); expect(schema.isFresh(10)).toBe(false); }); it('should use 10 minutes as default freshness threshold', () => { const old = new Date(Date.now() - 11 * 60 * 1000); // 11 minutes ago const schema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable], old); expect(schema.isFresh()).toBe(false); }); }); describe('getAgeInMinutes()', () => { it('should return age in minutes', () => { const tenMinutesAgo = new Date(Date.now() - 10 * 60 * 1000); const schema = new DatabaseSchema( 'db', Environment.DEVELOPMENT, [usersTable], tenMinutesAgo ); const age = schema.getAgeInMinutes(); expect(age).toBeGreaterThanOrEqual(9.9); expect(age).toBeLessThanOrEqual(10.1); }); }); describe('semantic intent preservation', () => { it('should preserve environment semantic', () => { const prodSchema = new DatabaseSchema('db', Environment.PRODUCTION, [usersTable], testDate); const devSchema = new DatabaseSchema('db', Environment.DEVELOPMENT, [usersTable], testDate); expect(prodSchema.environment).toBe(Environment.PRODUCTION); expect(devSchema.environment).toBe(Environment.DEVELOPMENT); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/semanticintent/semantic-d1-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server