import { describe, expect, it } from 'vitest'; import { MetadataService } from '../../src/services/metadata/metadata.service.js'; import type { AppMetadataSchema } from '@insforge/shared-schemas'; const metadataService = MetadataService.getInstance(); const sampleMetadata: AppMetadataSchema = { version: '1.2.3', auth: { oAuthProviders: ['google', 'github'], customOAuthProviders: [], smtpConfig: { enabled: false, host: '', port: 587, username: '', hasPassword: false, senderEmail: '', senderName: '', minIntervalSeconds: 60, }, requireEmailVerification: true, disableSignup: false, passwordMinLength: 8, requireNumber: false, requireLowercase: false, requireUppercase: false, requireSpecialChar: false, verifyEmailMethod: 'otp', resetPasswordMethod: 'otp', allowedRedirectUrls: [], }, database: { tables: [ { tableName: 'users', recordCount: 150 }, { tableName: 'posts', recordCount: 1200 }, ], totalSizeInGB: 0.3, }, storage: { buckets: [ { name: 'avatars', public: true, createdAt: '2026-01-01T00:00:00Z', objectCount: 42 }, ], totalSizeInGB: 0.5, }, functions: [ { slug: 'hello-world', name: 'hello-world', status: 'active', description: 'Test function' }, ], realtime: { channels: [ { id: '00000000-0000-0000-0000-000000000001', pattern: 'chat', description: null, webhookUrls: null, enabled: true, createdAt: '2026-01-01T00:00:00Z', updatedAt: '2026-01-01T00:00:00Z', }, ], permissions: { tables: {} }, }, }; describe('MetadataService.formatAsMarkdown', () => { it('renders a complete markdown document from metadata', () => { const md = metadataService.formatAsMarkdown(sampleMetadata); // Header expect(md).toContain('# Project Metadata'); expect(md).toContain('v1.2.3'); // Auth expect(md).toContain('## Auth'); expect(md).toContain('google, github'); expect(md).toContain('required'); expect(md).toContain('enabled'); // Database tables expect(md).toContain('| users | 150 |'); expect(md).toContain('| posts | 1200 |'); expect(md).toContain('0.3 GB'); // Storage expect(md).toContain('`avatars`'); expect(md).toContain('public'); expect(md).toContain('42 objects'); expect(md).toContain('0.5 GB'); // Functions expect(md).toContain('`hello-world`'); expect(md).toContain('active'); expect(md).toContain('Test function'); // Realtime expect(md).toContain('`chat`'); }); it('handles missing optional sections gracefully', () => { const minimal: AppMetadataSchema = { auth: { oAuthProviders: [], customOAuthProviders: [], smtpConfig: { enabled: false, host: '', port: 587, username: '', hasPassword: false, senderEmail: '', senderName: '', minIntervalSeconds: 60, }, requireEmailVerification: false, disableSignup: false, passwordMinLength: 8, requireNumber: false, requireLowercase: false, requireUppercase: false, requireSpecialChar: false, verifyEmailMethod: 'otp', resetPasswordMethod: 'otp', allowedRedirectUrls: [], }, database: { tables: [], totalSizeInGB: 0, }, storage: { buckets: [], totalSizeInGB: 0, }, functions: [], }; const md = metadataService.formatAsMarkdown(minimal); expect(md).toContain('# Project Metadata'); expect(md).toContain('No storage buckets configured.'); expect(md).toContain('No edge functions deployed.'); // Realtime section omitted entirely when undefined expect(md).not.toContain('## Realtime'); // Deployments section omitted for self-hosted expect(md).not.toContain('## Deployments'); }); it('renders database hint when present', () => { const withHint: AppMetadataSchema = { ...sampleMetadata, database: { tables: [{ tableName: 'users', recordCount: 10 }], totalSizeInGB: 0.1, hint: 'Consider adding indexes', }, }; const md = metadataService.formatAsMarkdown(withHint); expect(md).toContain('| users | 10 |'); expect(md).toContain('Consider adding indexes'); }); it('renders deployments section for cloud projects', () => { const withDeployments: AppMetadataSchema = { ...sampleMetadata, deployments: { customSlug: 'my-app' }, }; const md = metadataService.formatAsMarkdown(withDeployments); expect(md).toContain('## Deployments'); expect(md).toContain('`my-app`'); }); it('renders deployments with null slug', () => { const withNullSlug: AppMetadataSchema = { ...sampleMetadata, deployments: { customSlug: null }, }; const md = metadataService.formatAsMarkdown(withNullSlug); expect(md).toContain('## Deployments'); expect(md).toContain('not set'); }); it('preserves backticks in values using double-backtick code spans', () => { const withBackticks: AppMetadataSchema = { ...sampleMetadata, database: { tables: [{ tableName: 'users', recordCount: 10 }], totalSizeInGB: 0.1, hint: 'Use `auth.uid()` for RLS policies', }, functions: [ { slug: 'check-`role`', name: 'check-role', status: 'active', description: 'Validates `admin` access', }, ], }; const md = metadataService.formatAsMarkdown(withBackticks); // Hint is plain text — backticks preserved as-is expect(md).toContain('Use `auth.uid()` for RLS policies'); // Slug with backticks uses double-backtick code span expect(md).toContain('`` check-`role` ``'); // Description is plain text — backticks preserved expect(md).toContain('Validates `admin` access'); }); it('handles consecutive backtick runs with wider delimiters', () => { const withDoubleBackticks: AppMetadataSchema = { ...sampleMetadata, functions: [ { slug: 'a``b', name: 'a-b', status: 'active', description: '', }, ], }; const md = metadataService.formatAsMarkdown(withDoubleBackticks); // Double-backtick run in value requires triple-backtick delimiter expect(md).toContain('``` a``b ```'); }); it('escapes pipes in table cells without affecting code spans', () => { const withPipes: AppMetadataSchema = { ...sampleMetadata, database: { tables: [{ tableName: 'public|users', recordCount: 5 }], totalSizeInGB: 0.1, }, storage: { buckets: [{ name: 'a|b', public: true, createdAt: '2026-01-01T00:00:00Z', objectCount: 1 }], totalSizeInGB: 0, }, }; const md = metadataService.formatAsMarkdown(withPipes); // Pipes escaped in table cells expect(md).toContain('| public\\|users | 5 |'); // Bucket name in code span — pipes not escaped expect(md).toContain('`a|b`'); }); });