apple-hig-mcp
Version:
High-performance MCP server providing instant access to Apple's Human Interface Guidelines via hybrid static/dynamic content delivery
306 lines (298 loc) • 16.1 kB
JavaScript
/**
* Integration tests for Phase 1 and Phase 2 functionality
* Tests the complete pipeline from content processing to semantic search
*/
import { ContentProcessorService } from '../services/content-processor.service.js';
import { ContentQualityValidatorService } from '../services/content-quality-validator.service.js';
import { SearchIndexerService } from '../services/search-indexer.service.js';
// Mock external dependencies for integration testing
// TensorFlow removed - no longer needed
jest.mock('compromise', () => ({
__esModule: true,
default: jest.fn().mockReturnValue({
topics: () => ({ out: () => ['design', 'button', 'navigation'] }),
nouns: () => ({ out: () => ['button', 'interface', 'guidelines'] }),
adjectives: () => ({ out: () => ['interactive', 'accessible', 'intuitive'] })
})
}));
describe('Phase 1 & 2 Integration Tests', () => {
let contentProcessor;
let qualityValidator;
let searchIndexer;
const sampleHtml = `
<div class="main-content">
<h1>iOS Button Design Guidelines</h1>
<p>Buttons are interactive elements that allow users to trigger actions in your iOS app. They are fundamental components of the user interface.</p>
<h2>Design Principles</h2>
<p>When designing buttons for iOS applications, follow Apple's Human Interface Guidelines to ensure consistency and usability.</p>
<h3>Guidelines</h3>
<ul>
<li>Use clear, descriptive text that explains the button's action</li>
<li>Make buttons large enough for easy touch interaction (minimum 44pt)</li>
<li>Ensure sufficient contrast for accessibility compliance</li>
<li>Maintain consistent styling throughout your application</li>
</ul>
<h3>Examples</h3>
<ul>
<li>Primary buttons for main actions (Save, Submit, Continue)</li>
<li>Secondary buttons for alternative actions (Cancel, Back)</li>
<li>Destructive buttons for dangerous actions (Delete, Remove)</li>
</ul>
<h2>Technical Specifications</h2>
<p>iOS buttons should meet specific dimensional and spacing requirements.</p>
<h3>Dimensions</h3>
<ul>
<li>Minimum height: 44 points</li>
<li>Minimum width: 44 points for icon-only buttons</li>
<li>Recommended padding: 12 points horizontal, 8 points vertical</li>
</ul>
<h2>Code Implementation</h2>
<pre><code>
let button = UIButton(type: .system)
button.setTitle("Action", for: .normal)
button.frame = CGRect(x: 0, y: 0, width: 120, height: 44)
</code></pre>
<nav class="sidebar-nav">
<a href="/navigation">Navigation</a>
<a href="/tables">Tables</a>
</nav>
<img src="button-examples.png" alt="Button examples" />
</div>
`;
beforeEach(() => {
contentProcessor = new ContentProcessorService();
qualityValidator = new ContentQualityValidatorService({
minQualityScore: 0.6,
minConfidence: 0.7,
minContentLength: 200,
maxFallbackRate: 5,
minStructureScore: 0.5,
minAppleTermsScore: 0.3
});
searchIndexer = new SearchIndexerService(contentProcessor);
});
describe('Phase 1: Content Processing Pipeline', () => {
it('should process HTML through complete Phase 1 pipeline', async () => {
// Step 1: Process HTML content
const processedResult = await contentProcessor.processContent(sampleHtml, 'https://developer.apple.com/design/human-interface-guidelines/buttons');
// Verify content processing
expect(processedResult.cleanedMarkdown).toContain('# iOS Button Design Guidelines');
expect(processedResult.cleanedMarkdown).toContain('interactive elements');
expect(processedResult.cleanedMarkdown).not.toContain('<img');
expect(processedResult.cleanedMarkdown).not.toContain('<nav');
// Verify structured content extraction
expect(processedResult.structuredContent.overview).toContain('interactive elements');
expect(processedResult.structuredContent.guidelines.length).toBeGreaterThan(3);
expect(processedResult.structuredContent.examples.length).toBeGreaterThan(2);
expect(processedResult.structuredContent.specifications).toBeDefined();
expect(processedResult.structuredContent.specifications?.dimensions).toBeDefined();
// Verify quality metrics
expect(processedResult.quality.score).toBeGreaterThan(0.6);
expect(processedResult.quality.confidence).toBeGreaterThan(0.8);
expect(processedResult.quality.appleTermsScore).toBeGreaterThan(0.4);
expect(processedResult.quality.codeExamplesCount).toBeGreaterThan(0);
expect(processedResult.quality.headingCount).toBeGreaterThan(4);
expect(processedResult.quality.isFallbackContent).toBe(false);
// Step 2: Validate content quality
const section = {
id: 'buttons-ios',
title: 'iOS Buttons',
url: 'https://developer.apple.com/design/human-interface-guidelines/buttons',
platform: 'iOS',
category: 'visual-design',
quality: processedResult.quality
};
const validationResult = await qualityValidator.validateContent(processedResult.cleanedMarkdown, section);
expect(validationResult.isValid).toBe(true);
expect(validationResult.score).toBeGreaterThan(0.8);
expect(validationResult.issues).toHaveLength(0);
// Step 3: Record extraction for SLA monitoring
qualityValidator.recordExtraction(section, processedResult.quality);
const stats = qualityValidator.getStatistics();
expect(stats.totalSections).toBe(1);
expect(stats.fallbackUsage).toBe(0);
expect(stats.extractionSuccessRate).toBe(100);
expect(stats.averageQuality).toBeGreaterThan(0.6);
});
it('should meet Phase 1 SLA requirements', async () => {
// Process multiple sections to test SLA compliance
const testSections = [
{ html: sampleHtml, url: 'https://developer.apple.com/design/human-interface-guidelines/buttons' },
{ html: '<h1>Navigation</h1><p>Apple navigation guidelines for iOS apps.</p>', url: 'https://developer.apple.com/design/human-interface-guidelines/navigation' },
{ html: '<h1>Typography</h1><p>Text and font guidelines for iOS.</p>', url: 'https://developer.apple.com/design/human-interface-guidelines/typography' }
];
for (let i = 0; i < testSections.length; i++) {
const result = await contentProcessor.processContent(testSections[i].html, testSections[i].url);
const section = {
id: `section-${i}`,
title: `Section ${i}`,
url: testSections[i].url,
platform: 'iOS',
category: 'visual-design',
quality: result.quality
};
qualityValidator.recordExtraction(section, result.quality);
}
const stats = qualityValidator.getStatistics();
// Verify SLA compliance (95% real content target)
expect(stats.extractionSuccessRate).toBeGreaterThanOrEqual(95);
expect(stats.averageQuality).toBeGreaterThan(0.3);
expect(stats.averageConfidence).toBeGreaterThan(0.5);
});
});
describe('Phase 2: Semantic Search Pipeline', () => {
let processedSections;
beforeEach(async () => {
// Prepare test data by processing content through Phase 1 pipeline
const htmlSamples = [
{
html: sampleHtml,
title: 'iOS Buttons',
category: 'visual-design',
id: 'buttons-ios'
},
{
html: '<h1>Navigation Bars</h1><p>Navigation bars enable users to move through content hierarchy in iOS apps.</p><h2>Guidelines</h2><ul><li>Show current location</li><li>Provide clear back navigation</li></ul>',
title: 'Navigation Bars',
category: 'navigation',
id: 'navigation-ios'
},
{
html: '<h1>Color Guidelines</h1><p>Apple color guidelines ensure accessibility and brand consistency.</p><h2>Accessibility</h2><p>Maintain sufficient contrast ratios for text readability.</p>',
title: 'Color Guidelines',
category: 'color-and-materials',
id: 'color-universal'
}
];
processedSections = [];
for (const sample of htmlSamples) {
const result = await contentProcessor.processContent(sample.html, `https://developer.apple.com/design/human-interface-guidelines/${sample.id}`);
const section = {
id: sample.id,
title: sample.title,
url: `https://developer.apple.com/design/human-interface-guidelines/${sample.id}`,
platform: sample.id.includes('universal') ? 'universal' : 'iOS',
category: sample.category,
content: result.cleanedMarkdown,
structuredContent: result.structuredContent,
quality: result.quality
};
processedSections.push(section);
searchIndexer.addSection(section);
}
});
it('should index sections with semantic capabilities', () => {
const stats = searchIndexer.getStatistics();
expect(stats.keywordIndex.totalEntries).toBe(3);
expect(stats.keywordIndex.averageKeywordsPerSection).toBeGreaterThan(0);
expect(stats.capabilities.supportedFeatures).toContain('keyword-search');
expect(stats.capabilities.supportedFeatures).toContain('platform-filtering');
expect(stats.capabilities.supportedFeatures).toContain('category-filtering');
});
});
describe('End-to-End Integration', () => {
it('should complete full pipeline: HTML → Processing → Validation → Indexing → Search', async () => {
// Step 1: Process raw HTML
const processedResult = await contentProcessor.processContent(sampleHtml, 'https://developer.apple.com/design/human-interface-guidelines/buttons');
// Step 2: Validate quality
const section = {
id: 'buttons-ios-e2e',
title: 'iOS Buttons E2E',
url: 'https://developer.apple.com/design/human-interface-guidelines/buttons',
platform: 'iOS',
category: 'visual-design',
content: processedResult.cleanedMarkdown,
structuredContent: processedResult.structuredContent,
quality: processedResult.quality
};
const validationResult = await qualityValidator.validateContent(processedResult.cleanedMarkdown, section);
expect(validationResult.isValid).toBe(true);
// Step 3: Index for search
searchIndexer.addSection(section);
// Step 4: Search and verify results
const searchResults = await searchIndexer.search('iOS button interaction guidelines', [section], { useSemanticSearch: false, limit: 5 });
expect(searchResults.length).toBe(1);
expect(searchResults[0].title).toBe('iOS Buttons E2E');
expect(searchResults[0].relevanceScore).toBeGreaterThan(0);
// Step 5: Pipeline complete - all steps verified successfully
});
it('should handle poor quality content gracefully throughout pipeline', async () => {
const poorHtml = '<div>Loading...</div>';
// Process poor content
const result = await contentProcessor.processContent(poorHtml, 'https://example.com/poor-content');
expect(result.quality.score).toBeLessThan(0.5);
expect(result.quality.isFallbackContent).toBe(false); // Not fallback, just poor
// Validate poor content
const poorSection = {
id: 'poor-content',
title: 'Poor Content',
url: 'https://example.com/poor-content',
platform: 'iOS',
category: 'visual-design',
quality: result.quality
};
const validation = await qualityValidator.validateContent(result.cleanedMarkdown, poorSection);
expect(validation.isValid).toBe(false);
expect(validation.issues.length).toBeGreaterThan(0);
// Poor content should still be indexable but with low quality
poorSection.content = result.cleanedMarkdown;
searchIndexer.addSection(poorSection);
const stats = searchIndexer.getStatistics();
expect(stats.keywordIndex.totalEntries).toBeGreaterThan(0);
});
});
describe('Performance and SLA Compliance', () => {
it('should meet performance requirements', async () => {
const startTime = Date.now();
// Process content
const result = await contentProcessor.processContent(sampleHtml, 'https://developer.apple.com/design/human-interface-guidelines/buttons');
const processingTime = Date.now() - startTime;
expect(processingTime).toBeLessThan(1000); // Under 1 second
// Search should be fast
const section = {
id: 'perf-test',
title: 'Performance Test',
url: 'https://example.com',
platform: 'iOS',
category: 'visual-design',
content: result.cleanedMarkdown,
quality: result.quality
};
searchIndexer.addSection(section);
const searchStart = Date.now();
const searchResults = await searchIndexer.search('button', [section], {
useSemanticSearch: false,
limit: 5
});
const searchTime = Date.now() - searchStart;
expect(searchTime).toBeLessThan(100); // Under 100ms for keyword search
expect(searchResults.length).toBeGreaterThan(0);
});
it('should maintain quality SLA across multiple extractions', async () => {
const htmlSamples = [
'<h1>Buttons</h1><p>iOS button guidelines from Apple.</p>',
'<h1>Navigation</h1><p>Apple navigation patterns for iOS.</p>',
'<h1>Tables</h1><p>iOS table design guidelines.</p>',
'<h1>Alerts</h1><p>Apple alert design for iOS apps.</p>',
'<h1>Sheets</h1><p>iOS action sheets and modals.</p>'
];
for (let i = 0; i < htmlSamples.length; i++) {
const result = await contentProcessor.processContent(htmlSamples[i], `https://developer.apple.com/design/sample-${i}`);
const section = {
id: `sla-test-${i}`,
title: `SLA Test ${i}`,
url: `https://developer.apple.com/design/sample-${i}`,
platform: 'iOS',
category: 'visual-design',
quality: result.quality
};
qualityValidator.recordExtraction(section, result.quality);
}
const stats = qualityValidator.getStatistics();
// Should meet SLA targets
expect(stats.extractionSuccessRate).toBeGreaterThanOrEqual(95);
expect(stats.averageQuality).toBeGreaterThan(0.1);
});
});
});
//# sourceMappingURL=integration.test.js.map