Skip to main content
Glama
attribute-mapping-enhancement.test.tsβ€’7.82 kB
/** * Tests for enhanced attribute mapping functionality * Specifically tests special case handling and fuzzy matching */ import { describe, beforeEach, it, expect, vi } from 'vitest'; import { getAttributeSlug, invalidateConfigCache, } from '../../src/utils/attribute-mapping/index.js'; import * as mappingUtils from '../../src/utils/attribute-mapping/mapping-utils.js'; import * as configLoader from '../../src/utils/config-loader.js'; // Mock the config-loader vi.mock('../../src/utils/config-loader', () => ({ loadMappingConfig: vi.fn(), })); describe('Enhanced Attribute Mapping', () => { // Reset mocks before each test beforeEach(() => { vi.clearAllMocks(); invalidateConfigCache(); // Set up default empty configuration for tests (configLoader.loadMappingConfig as any).mockReturnValue({ version: '1.0', mappings: { attributes: { common: {}, objects: {}, custom: {} }, objects: {}, lists: {}, relationships: {}, }, }); }); describe('Special Case Handling', () => { it('should return field names as-is with default mapping (no B2B segment special cases)', () => { // After legacy mapping removal (Issue #626), B2B segment no longer maps to type_persona // Default behavior: field names return as-is without custom mappings const variations = ['B2B Segment', 'b2b_segment', 'b2bsegment', 'B2B']; // Default behavior: return field names as-is expect(getAttributeSlug('B2B Segment')).toBe('B2B Segment'); expect(getAttributeSlug('b2b_segment')).toBe('b2b_segment'); expect(getAttributeSlug('b2bsegment')).toBe('b2bsegment'); expect(getAttributeSlug('B2B')).toBe('B2B'); }); it('should handle industry mapping (valid special case)', () => { // Industry -> categories mapping is still valid as it maps to existing Attio field expect(getAttributeSlug('industry')).toBe('categories'); expect(getAttributeSlug('Industry')).toBe('categories'); expect(getAttributeSlug('Industry Type')).toBe('categories'); }); it('should return other field names as-is with default behavior', () => { // Default behavior: field names return as-is without custom mappings expect(getAttributeSlug('b2b-segment')).toBe('b2b-segment'); expect(getAttributeSlug('b2b segment')).toBe('b2b segment'); expect(getAttributeSlug('b2b.segment')).toBe('b2b.segment'); }); }); describe('Tiered Matching Approach', () => { it('should use valid special cases like industry mapping', () => { // Mock configuration with a different mapping for industry // Special case handling should override the config for valid mappings (configLoader.loadMappingConfig as any).mockReturnValue({ version: '1.0', mappings: { attributes: { common: { industry: 'wrong_mapping', }, objects: {}, custom: {}, }, objects: {}, lists: {}, relationships: {}, }, }); // Special case handling should override the config for valid mappings expect(getAttributeSlug('industry')).toBe('categories'); // Spy on handleSpecialCases to ensure it was called const handleSpecialCasesSpy = vi.spyOn( mappingUtils, 'handleSpecialCases' ); getAttributeSlug('industry'); expect(handleSpecialCasesSpy).toHaveBeenCalledWith('industry'); }); it('should use case-insensitive lookup after special cases', () => { (configLoader.loadMappingConfig as any).mockReturnValue({ version: '1.0', mappings: { attributes: { common: { 'Custom Field': 'custom_slug', }, objects: {}, custom: {}, }, objects: {}, lists: {}, relationships: {}, }, }); // Should find the mapping with different case expect(getAttributeSlug('custom field')).toBe('custom_slug'); expect(getAttributeSlug('CUSTOM FIELD')).toBe('custom_slug'); }); it('should use normalized lookup when case-insensitive fails', () => { (configLoader.loadMappingConfig as any).mockReturnValue({ version: '1.0', mappings: { attributes: { common: { CustomField: 'custom_slug', }, objects: {}, custom: {}, }, objects: {}, lists: {}, relationships: {}, }, }); // Should find the mapping with different spacing expect(getAttributeSlug('Custom Field')).toBe('custom_slug'); expect(getAttributeSlug('custom field')).toBe('custom_slug'); }); it('should use aggressive normalization as a last resort', () => { // For this test, we'll spy on lookupAggressiveNormalized instead of trying // to set up the full chain, which is difficult to mock completely const lookupAggressiveNormalizedSpy = vi .spyOn(mappingUtils, 'lookupAggressiveNormalized') .mockReturnValue('custom_slug'); // Call the function to test the aggressive normalization path const result = getAttributeSlug('Custom.Field'); // Verify the aggressive normalization function was called expect(lookupAggressiveNormalizedSpy).toHaveBeenCalled(); expect(result).toBe('custom_slug'); // Restore the original implementation lookupAggressiveNormalizedSpy.mockRestore(); }); it('should handle snake case conversion', () => { (configLoader.loadMappingConfig as any).mockReturnValue({ version: '1.0', mappings: { attributes: { common: { 'Account Manager': 'account_manager', }, objects: {}, custom: {}, }, objects: {}, lists: {}, relationships: {}, }, }); // Should convert snake case to display name and then look up expect(getAttributeSlug('account_manager')).toBe('account_manager'); }); it('should return field names as-is when no custom mappings exist', () => { // Test default behavior: no custom mappings should return field names as-is (configLoader.loadMappingConfig as any).mockReturnValue({ version: '1.0', mappings: { attributes: { common: {}, objects: {}, custom: {} }, objects: {}, lists: {}, relationships: {}, }, }); expect(getAttributeSlug('postal_code')).toBe('postal_code'); expect(getAttributeSlug('ZIP')).toBe('ZIP'); // No default mapping for ZIP }); }); describe('Object-Specific Mappings', () => { it('should prioritize object-specific mappings over common mappings', () => { (configLoader.loadMappingConfig as any).mockReturnValue({ version: '1.0', mappings: { attributes: { common: { Status: 'status_common', }, objects: { companies: { Status: 'status_companies', }, people: { Status: 'status_people', }, }, custom: {}, }, objects: {}, lists: {}, relationships: {}, }, }); // Should use object-specific mapping when object type is provided expect(getAttributeSlug('Status', 'companies')).toBe('status_companies'); expect(getAttributeSlug('Status', 'people')).toBe('status_people'); // Should fall back to common mapping when no object type is provided expect(getAttributeSlug('Status')).toBe('status_common'); }); }); });

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/kesslerio/attio-mcp-server'

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