Skip to main content
Glama
1yhy
by 1yhy
icon-optimization.test.ts10.3 kB
/** * Icon Detection Optimization Tests * * Verifies that the optimized collectNodeStats() function produces * identical results to the original individual functions. */ import { describe, it, expect } from "vitest"; // Test the internal implementation // We'll create mock nodes and verify the stats are correctly computed interface MockNode { id: string; name: string; type: string; children?: MockNode[]; absoluteBoundingBox?: { x: number; y: number; width: number; height: number }; fills?: Array<{ type: string; visible?: boolean; imageRef?: string }>; effects?: Array<{ type: string; visible?: boolean }>; } // Helper functions to test (matching the original implementations) const CONTAINER_TYPES = ["GROUP", "FRAME", "COMPONENT", "INSTANCE"]; const MERGEABLE_TYPES = [ "VECTOR", "RECTANGLE", "ELLIPSE", "LINE", "POLYGON", "STAR", "BOOLEAN_OPERATION", "REGULAR_POLYGON", ]; const EXCLUDE_TYPES = ["TEXT", "COMPONENT", "INSTANCE"]; const PNG_REQUIRED_EFFECTS = ["DROP_SHADOW", "INNER_SHADOW", "LAYER_BLUR", "BACKGROUND_BLUR"]; function isContainerType(type: string): boolean { return CONTAINER_TYPES.includes(type); } function isMergeableType(type: string): boolean { return MERGEABLE_TYPES.includes(type); } function isExcludeType(type: string): boolean { return EXCLUDE_TYPES.includes(type); } function hasImageFill(node: MockNode): boolean { if (!node.fills) return false; return node.fills.some( (fill) => fill.type === "IMAGE" && fill.visible !== false && fill.imageRef, ); } function hasComplexEffects(node: MockNode): boolean { if (!node.effects) return false; return node.effects.some( (effect) => effect.visible !== false && PNG_REQUIRED_EFFECTS.includes(effect.type), ); } // Original functions (for comparison) function calculateDepthOriginal(node: MockNode, currentDepth: number = 0): number { if (!node.children || node.children.length === 0) { return currentDepth; } return Math.max(...node.children.map((child) => calculateDepthOriginal(child, currentDepth + 1))); } function countTotalChildrenOriginal(node: MockNode): number { if (!node.children || node.children.length === 0) { return 0; } return node.children.reduce((sum, child) => sum + 1 + countTotalChildrenOriginal(child), 0); } function hasExcludeTypeInTreeOriginal(node: MockNode): boolean { if (isExcludeType(node.type)) { return true; } if (node.children) { return node.children.some((child) => hasExcludeTypeInTreeOriginal(child)); } return false; } function hasImageFillInTreeOriginal(node: MockNode): boolean { if (hasImageFill(node)) { return true; } if (node.children) { return node.children.some((child) => hasImageFillInTreeOriginal(child)); } return false; } function hasComplexEffectsInTreeOriginal(node: MockNode): boolean { if (hasComplexEffects(node)) { return true; } if (node.children) { return node.children.some((child) => hasComplexEffectsInTreeOriginal(child)); } return false; } function areAllLeavesMergeableOriginal(node: MockNode): boolean { if (!node.children || node.children.length === 0) { return isMergeableType(node.type); } if (isContainerType(node.type)) { return node.children.every((child) => areAllLeavesMergeableOriginal(child)); } return isMergeableType(node.type); } // Optimized single-pass function interface NodeTreeStats { depth: number; totalChildren: number; hasExcludeType: boolean; hasImageFill: boolean; hasComplexEffects: boolean; allLeavesMergeable: boolean; mergeableRatio: number; } function collectNodeStats(node: MockNode): NodeTreeStats { if (!node.children || node.children.length === 0) { const isMergeable = isMergeableType(node.type); return { depth: 0, totalChildren: 0, hasExcludeType: isExcludeType(node.type), hasImageFill: hasImageFill(node), hasComplexEffects: hasComplexEffects(node), allLeavesMergeable: isMergeable, mergeableRatio: isMergeable ? 1 : 0, }; } const childStats = node.children.map(collectNodeStats); const maxChildDepth = Math.max(...childStats.map((s) => s.depth)); const totalDescendants = childStats.reduce((sum, s) => sum + 1 + s.totalChildren, 0); const hasExcludeInChildren = childStats.some((s) => s.hasExcludeType); const hasImageInChildren = childStats.some((s) => s.hasImageFill); const hasEffectsInChildren = childStats.some((s) => s.hasComplexEffects); const allChildrenMergeable = childStats.every((s) => s.allLeavesMergeable); const mergeableCount = node.children.filter( (child) => isMergeableType(child.type) || isContainerType(child.type), ).length; const mergeableRatio = mergeableCount / node.children.length; const allLeavesMergeable = isContainerType(node.type) ? allChildrenMergeable : isMergeableType(node.type); return { depth: maxChildDepth + 1, totalChildren: totalDescendants, hasExcludeType: isExcludeType(node.type) || hasExcludeInChildren, hasImageFill: hasImageFill(node) || hasImageInChildren, hasComplexEffects: hasComplexEffects(node) || hasEffectsInChildren, allLeavesMergeable, mergeableRatio, }; } describe("Icon Detection Optimization", () => { describe("collectNodeStats equivalence", () => { const testCases: { name: string; node: MockNode }[] = [ { name: "simple leaf node", node: { id: "1", name: "Vector", type: "VECTOR", }, }, { name: "leaf node with excludable type", node: { id: "1", name: "Text", type: "TEXT", }, }, { name: "container with vector children", node: { id: "1", name: "Group", type: "GROUP", children: [ { id: "2", name: "Vector1", type: "VECTOR" }, { id: "3", name: "Vector2", type: "VECTOR" }, ], }, }, { name: "nested container", node: { id: "1", name: "Frame", type: "FRAME", children: [ { id: "2", name: "Group", type: "GROUP", children: [ { id: "3", name: "Ellipse", type: "ELLIPSE" }, { id: "4", name: "Rect", type: "RECTANGLE" }, ], }, ], }, }, { name: "container with text child", node: { id: "1", name: "Button", type: "FRAME", children: [ { id: "2", name: "BG", type: "RECTANGLE" }, { id: "3", name: "Label", type: "TEXT" }, ], }, }, { name: "node with image fill", node: { id: "1", name: "Image", type: "RECTANGLE", fills: [{ type: "IMAGE", visible: true, imageRef: "abc123" }], }, }, { name: "node with complex effects", node: { id: "1", name: "Shadow Box", type: "FRAME", effects: [{ type: "DROP_SHADOW", visible: true }], children: [{ id: "2", name: "Content", type: "RECTANGLE" }], }, }, { name: "deeply nested structure", node: { id: "1", name: "Root", type: "FRAME", children: [ { id: "2", name: "Level1", type: "GROUP", children: [ { id: "3", name: "Level2", type: "GROUP", children: [ { id: "4", name: "Level3", type: "GROUP", children: [{ id: "5", name: "Leaf", type: "VECTOR" }], }, ], }, ], }, ], }, }, ]; testCases.forEach(({ name, node }) => { it(`should produce equivalent results for: ${name}`, () => { const stats = collectNodeStats(node); // Compare with original functions expect(stats.depth).toBe(calculateDepthOriginal(node)); expect(stats.totalChildren).toBe(countTotalChildrenOriginal(node)); expect(stats.hasExcludeType).toBe(hasExcludeTypeInTreeOriginal(node)); expect(stats.hasImageFill).toBe(hasImageFillInTreeOriginal(node)); expect(stats.hasComplexEffects).toBe(hasComplexEffectsInTreeOriginal(node)); expect(stats.allLeavesMergeable).toBe(areAllLeavesMergeableOriginal(node)); }); }); }); describe("edge cases", () => { it("should handle empty children array", () => { const node: MockNode = { id: "1", name: "Empty", type: "GROUP", children: [], }; const stats = collectNodeStats(node); expect(stats.depth).toBe(0); expect(stats.totalChildren).toBe(0); }); it("should handle invisible fills", () => { const node: MockNode = { id: "1", name: "Hidden Image", type: "RECTANGLE", fills: [{ type: "IMAGE", visible: false, imageRef: "abc123" }], }; const stats = collectNodeStats(node); expect(stats.hasImageFill).toBe(false); }); it("should handle invisible effects", () => { const node: MockNode = { id: "1", name: "Hidden Shadow", type: "RECTANGLE", effects: [{ type: "DROP_SHADOW", visible: false }], }; const stats = collectNodeStats(node); expect(stats.hasComplexEffects).toBe(false); }); it("should calculate correct mergeable ratio", () => { const node: MockNode = { id: "1", name: "Mixed", type: "FRAME", children: [ { id: "2", name: "V1", type: "VECTOR" }, { id: "3", name: "V2", type: "VECTOR" }, { id: "4", name: "Unknown", type: "UNKNOWN_TYPE" }, { id: "5", name: "G1", type: "GROUP" }, ], }; const stats = collectNodeStats(node); // 3 mergeable (2 VECTOR + 1 GROUP) out of 4 expect(stats.mergeableRatio).toBe(0.75); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/1yhy/Figma-Context-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server