Files
wehub-resource-sync 3a28426bf4
Lint and Format Check / lint-and-format (push) Failing after 0s
Check Migrations / Check for duplicate migration numbers (push) Failing after 1s
CI Pre-merge Check / CI Pre-merge Check (push) Failing after 2m17s
chore: import upstream snapshot with attribution
2026-07-13 12:23:40 +08:00

255 lines
7.0 KiB
TypeScript

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`');
});
});