fix: resolve CI test failures and Docker build issues

- Fix template service tests to include description field
- Add missing repository methods for metadata queries
- Fix metadata generator test mocking issues
- Add missing runtime dependencies (openai, zod) to package.runtime.json
- Update test expectations for new template format

Fixes CI failures in PR #194

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
czlonkowski
2025-09-15 01:12:42 +02:00
parent c18c4e7584
commit 0c4a2199f5
4 changed files with 99 additions and 12 deletions

View File

@@ -9,7 +9,9 @@
"dotenv": "^16.5.0",
"sql.js": "^1.13.0",
"uuid": "^10.0.0",
"axios": "^1.7.7"
"axios": "^1.7.7",
"openai": "^4.77.0",
"zod": "^3.24.1"
},
"engines": {
"node": ">=16.0.0"

View File

@@ -809,4 +809,85 @@ export class TemplateRepository {
const results = this.db.prepare(query).all(complexity, limit, offset) as StoredTemplate[];
return results.map(t => this.decompressWorkflow(t));
}
/**
* Get count of templates matching metadata search
*/
getSearchTemplatesByMetadataCount(filters: {
category?: string;
complexity?: 'simple' | 'medium' | 'complex';
maxSetupMinutes?: number;
minSetupMinutes?: number;
requiredService?: string;
targetAudience?: string;
}): number {
let sql = `
SELECT COUNT(*) as count FROM templates
WHERE metadata_json IS NOT NULL
`;
const params: any[] = [];
if (filters.category) {
sql += ` AND json_extract(metadata_json, '$.categories') LIKE ?`;
params.push(`%"${filters.category}"%`);
}
if (filters.complexity) {
sql += ` AND json_extract(metadata_json, '$.complexity') = ?`;
params.push(filters.complexity);
}
if (filters.maxSetupMinutes !== undefined) {
sql += ` AND CAST(json_extract(metadata_json, '$.estimated_setup_minutes') AS INTEGER) <= ?`;
params.push(filters.maxSetupMinutes);
}
if (filters.minSetupMinutes !== undefined) {
sql += ` AND CAST(json_extract(metadata_json, '$.estimated_setup_minutes') AS INTEGER) >= ?`;
params.push(filters.minSetupMinutes);
}
if (filters.requiredService) {
sql += ` AND json_extract(metadata_json, '$.required_services') LIKE ?`;
params.push(`%"${filters.requiredService}"%`);
}
if (filters.targetAudience) {
sql += ` AND json_extract(metadata_json, '$.target_audience') LIKE ?`;
params.push(`%"${filters.targetAudience}"%`);
}
const result = this.db.prepare(sql).get(...params) as { count: number };
return result?.count || 0;
}
/**
* Get unique categories from metadata
*/
getUniqueCategories(): string[] {
const sql = `
SELECT DISTINCT value as category
FROM templates, json_each(metadata_json, '$.categories')
WHERE metadata_json IS NOT NULL
ORDER BY category
`;
const results = this.db.prepare(sql).all() as { category: string }[];
return results.map(r => r.category);
}
/**
* Get unique target audiences from metadata
*/
getUniqueTargetAudiences(): string[] {
const sql = `
SELECT DISTINCT value as audience
FROM templates, json_each(metadata_json, '$.target_audience')
WHERE metadata_json IS NOT NULL
ORDER BY audience
`;
const results = this.db.prepare(sql).all() as { audience: string }[];
return results.map(r => r.audience);
}
}

View File

@@ -350,8 +350,8 @@ describe('TemplateService', () => {
expect(result).toEqual({
items: [
{ id: 1, name: 'Template A', views: 200, nodeCount: 2 },
{ id: 2, name: 'Template B', views: 150, nodeCount: 1 }
{ id: 1, name: 'Template A', description: 'Description for template 1', views: 200, nodeCount: 2 },
{ id: 2, name: 'Template B', description: 'Description for template 2', views: 150, nodeCount: 1 }
],
total: 50,
limit: 10,

View File

@@ -370,13 +370,20 @@ describe('MetadataGenerator', () => {
});
it('should handle network timeouts gracefully in generateSingle', async () => {
// Mock OpenAI to simulate timeout
const mockClient = generator['client'];
const originalCreate = mockClient.chat.completions.create;
// Create a new generator with mocked OpenAI client
const mockClient = {
chat: {
completions: {
create: vi.fn().mockRejectedValue(new Error('Request timed out'))
}
}
};
mockClient.chat.completions.create = vi.fn().mockRejectedValue(
new Error('Request timed out')
);
// Override the client property using Object.defineProperty
Object.defineProperty(generator, 'client', {
value: mockClient,
writable: true
});
const template: MetadataRequest = {
templateId: 555,
@@ -388,9 +395,6 @@ describe('MetadataGenerator', () => {
// Should return default metadata instead of throwing
expect(result).toEqual(generator['getDefaultMetadata']());
// Restore original method
mockClient.chat.completions.create = originalCreate;
});
});