apple-hig-mcp
Version:
High-performance MCP server providing instant access to Apple's Human Interface Guidelines via hybrid static/dynamic content delivery
210 lines • 11 kB
JavaScript
/**
* Comprehensive Search Test Suite
*
* Tests authentication, UI patterns, and other key HIG searches
* to ensure the MCP covers the majority of areas across the HIG.
*/
import { HIGToolProvider } from '../tools.js';
import { HIGCache } from '../cache.js';
import { CrawleeHIGService } from '../services/crawlee-hig.service.js';
import { HIGResourceProvider } from '../resources.js';
import { HIGStaticContentProvider } from '../static-content.js';
describe('Comprehensive Search Functionality', () => {
let toolProvider;
let staticProvider;
beforeAll(async () => {
const cache = new HIGCache(3600);
const crawleeService = new CrawleeHIGService(cache);
staticProvider = new HIGStaticContentProvider();
const resourceProvider = new HIGResourceProvider(crawleeService, cache, staticProvider);
toolProvider = new HIGToolProvider(crawleeService, cache, resourceProvider, staticProvider);
await staticProvider.initialize();
});
describe('Authentication & Security Searches', () => {
const authenticationQueries = [
{ query: 'sign in with apple', expectedMinResults: 1, expectedTopResult: 'Sign in with Apple' },
{ query: 'privacy security', expectedMinResults: 1, expectedTopResult: 'Privacy' },
{ query: 'authentication', expectedMinResults: 1 },
{ query: 'login', expectedMinResults: 1 },
{ query: 'password', expectedMinResults: 1 },
{ query: 'sign in sign up', expectedMinResults: 1 },
{ query: 'social login', expectedMinResults: 1 },
{ query: 'apple google social authentication', expectedMinResults: 1 }
];
test.each(authenticationQueries)('should find results for "$query"', async ({ query, expectedMinResults, expectedTopResult }) => {
const result = await toolProvider.searchGuidelines({ query, limit: 5 });
expect(result.total).toBeGreaterThanOrEqual(expectedMinResults);
expect(result.results).toHaveLength(Math.min(5, result.total));
if (expectedTopResult) {
expect(result.results[0].title).toBe(expectedTopResult);
}
// All results should have relevance scores
result.results.forEach(r => {
expect(r.relevanceScore).toBeGreaterThan(0);
expect(r.title).toBeTruthy();
expect(r.platform).toBeTruthy();
});
});
});
describe('UI Component & Pattern Searches', () => {
const uiQueries = [
{ query: 'button', expectedMinResults: 1, expectedTopResult: 'Buttons' },
{ query: 'navigation', expectedMinResults: 1 },
{ query: 'alert', expectedMinResults: 1, expectedTopResult: 'Alerts' },
{ query: 'text field', expectedMinResults: 1, expectedTopResult: 'Text Fields' },
{ query: 'menu', expectedMinResults: 1 },
{ query: 'toolbar', expectedMinResults: 1 },
{ query: 'tab bar', expectedMinResults: 1, expectedTopResult: 'Tab Bars' },
{ query: 'modal', expectedMinResults: 1 },
{ query: 'popup', expectedMinResults: 1 },
{ query: 'dropdown', expectedMinResults: 1 }
];
test.each(uiQueries)('should find UI components for "$query"', async ({ query, expectedMinResults, expectedTopResult }) => {
const result = await toolProvider.searchGuidelines({ query, limit: 5 });
expect(result.total).toBeGreaterThanOrEqual(expectedMinResults);
if (expectedTopResult) {
expect(result.results[0].title).toBe(expectedTopResult);
}
});
});
describe('Error Handling & Validation Searches', () => {
const errorQueries = [
{ query: 'error handling', expectedMinResults: 1 },
{ query: 'validation', expectedMinResults: 1 },
{ query: 'error message', expectedMinResults: 1 },
{ query: 'feedback', expectedMinResults: 1 },
{ query: 'warning', expectedMinResults: 1 },
{ query: 'notification', expectedMinResults: 1, expectedTopResult: 'Notifications' }
];
test.each(errorQueries)('should find error handling content for "$query"', async ({ query, expectedMinResults, expectedTopResult }) => {
const result = await toolProvider.searchGuidelines({ query, limit: 5 });
expect(result.total).toBeGreaterThanOrEqual(expectedMinResults);
if (expectedTopResult) {
expect(result.results[0].title).toBe(expectedTopResult);
}
});
});
describe('Accessibility & Usability Searches', () => {
const accessibilityQueries = [
{ query: 'accessibility', expectedMinResults: 1 },
{ query: 'voiceover', expectedMinResults: 1 },
{ query: 'touch target', expectedMinResults: 1 },
{ query: 'color contrast', expectedMinResults: 1 },
{ query: 'inclusive design', expectedMinResults: 1 },
{ query: 'dark mode', expectedMinResults: 1, expectedTopResult: 'Dark Mode' }
];
test.each(accessibilityQueries)('should find accessibility content for "$query"', async ({ query, expectedMinResults, expectedTopResult }) => {
const result = await toolProvider.searchGuidelines({ query, limit: 5 });
expect(result.total).toBeGreaterThanOrEqual(expectedMinResults);
if (expectedTopResult) {
expect(result.results[0].title).toBe(expectedTopResult);
}
});
});
describe('Platform-Specific Searches', () => {
const platformQueries = [
{ query: 'ios design', platform: 'iOS', expectedMinResults: 1 },
{ query: 'macos design', platform: 'macOS', expectedMinResults: 1 },
{ query: 'watchos design', platform: 'watchOS', expectedMinResults: 1 },
{ query: 'visionos design', platform: 'visionOS', expectedMinResults: 1 },
{ query: 'tvos design', platform: 'tvOS', expectedMinResults: 1 }
];
test.each(platformQueries)('should find platform-specific content for "$query" on $platform', async ({ query, platform, expectedMinResults }) => {
const result = await toolProvider.searchGuidelines({
query,
platform: platform,
limit: 5
});
expect(result.total).toBeGreaterThanOrEqual(expectedMinResults);
// Results should be filtered to the specified platform or universal
result.results.forEach(r => {
expect(['universal', platform]).toContain(r.platform);
});
});
});
describe('Design System & Visual Searches', () => {
const visualQueries = [
{ query: 'color', expectedMinResults: 1, expectedTopResult: 'Color' },
{ query: 'typography', expectedMinResults: 1, expectedTopResult: 'Typography' },
{ query: 'icon', expectedMinResults: 1 },
{ query: 'layout', expectedMinResults: 1, expectedTopResult: 'Layout' },
{ query: 'spacing', expectedMinResults: 1 },
{ query: 'material', expectedMinResults: 1, expectedTopResult: 'Materials' },
{ query: 'animation', expectedMinResults: 1 },
{ query: 'motion', expectedMinResults: 1, expectedTopResult: 'Motion' }
];
test.each(visualQueries)('should find visual design content for "$query"', async ({ query, expectedMinResults, expectedTopResult }) => {
const result = await toolProvider.searchGuidelines({ query, limit: 5 });
expect(result.total).toBeGreaterThanOrEqual(expectedMinResults);
if (expectedTopResult) {
expect(result.results[0].title).toBe(expectedTopResult);
}
});
});
describe('Search Quality Metrics', () => {
test('should return results with proper relevance scoring', async () => {
const result = await toolProvider.searchGuidelines({
query: 'sign in with apple',
limit: 5
});
// Scores should be in descending order
for (let i = 1; i < result.results.length; i++) {
expect(result.results[i - 1].relevanceScore).toBeGreaterThanOrEqual(result.results[i].relevanceScore);
}
// All scores should be positive
result.results.forEach(r => {
expect(r.relevanceScore).toBeGreaterThan(0);
});
});
test('should handle edge cases gracefully', async () => {
const edgeCases = [
'', // Empty query
' ', // Whitespace only
'nonexistenttermasdfgh', // Non-existent term
'a', // Very short query
'the and or but', // Only common words
];
for (const query of edgeCases) {
const result = await toolProvider.searchGuidelines({ query, limit: 5 });
expect(result).toBeDefined();
expect(result.total).toBeGreaterThanOrEqual(0);
expect(Array.isArray(result.results)).toBe(true);
}
});
test('should respect category filters', async () => {
const result = await toolProvider.searchGuidelines({
query: 'button',
category: 'selection-and-input',
limit: 5
});
result.results.forEach(r => {
expect(r.category).toBe('selection-and-input');
});
});
});
describe('Content Coverage Verification', () => {
test('should have comprehensive coverage of HIG areas', async () => {
const coverageQueries = [
'privacy', 'accessibility', 'authentication', 'button',
'navigation', 'alert', 'color', 'typography', 'layout',
'error', 'validation', 'notification', 'menu', 'form'
];
let totalResults = 0;
let queriesWithResults = 0;
for (const query of coverageQueries) {
const result = await toolProvider.searchGuidelines({ query, limit: 1 });
totalResults += result.total;
if (result.total > 0) {
queriesWithResults++;
}
}
// At least 90% of queries should return results
const coveragePercentage = (queriesWithResults / coverageQueries.length) * 100;
expect(coveragePercentage).toBeGreaterThanOrEqual(90);
// Should have a reasonable total number of results across all queries
// In test environment, expect at least one result per query on average
expect(totalResults).toBeGreaterThanOrEqual(coverageQueries.length);
});
});
});
//# sourceMappingURL=search-comprehensive.test.js.map