UNPKG

polen

Version:

A framework for delightful GraphQL developer portals

249 lines (208 loc) 7.65 kB
/** * @vitest-environment jsdom */ import { describe, expect, it } from 'vitest' import { createSimpleOverlay, createSimplePositionCalculator } from './positioning-simple.js' import type { Identifier } from './types.js' // Helper to create test identifier const createTestIdentifier = ( name: string, line: number, column: number, kind: Identifier['kind'] = 'Field', ): Identifier => ({ name, kind, position: { start: column - 1, end: column - 1 + name.length, line, column, }, schemaPath: [name], context: { selectionPath: [] }, }) describe('Simple Positioning Engine', () => { describe('SimplePositionCalculator', () => { const calculator = createSimplePositionCalculator() it('should wrap identifiers in spans', () => { const container = document.createElement('div') container.innerHTML = ` <pre class="code-block"> <code>query GetUser { user { name } }</code> </pre> ` const identifiers = [ createTestIdentifier('query', 1, 1), createTestIdentifier('user', 2, 3, 'Field'), createTestIdentifier('name', 3, 5, 'Field'), ] const codeElement = container.querySelector('code')! calculator.prepareCodeBlock(codeElement, identifiers) // Check that identifiers were wrapped const wrappedElements = container.querySelectorAll('[data-graphql-id]') expect(wrappedElements.length).toBe(3) // Check first wrapped element const firstWrapped = wrappedElements[0] as HTMLElement expect(firstWrapped.textContent).toBe('query') expect(firstWrapped.getAttribute('data-graphql-name')).toBe('query') expect(firstWrapped.getAttribute('data-graphql-kind')).toBe('Field') }) it('should handle multiple identifiers in same line', () => { const container = document.createElement('div') container.innerHTML = ` <pre class="code-block"> <code>query GetUserById($id: ID!) {</code> </pre> ` const identifiers = [ createTestIdentifier('query', 1, 1), createTestIdentifier('GetUserById', 1, 7), createTestIdentifier('$id', 1, 19, 'Variable'), createTestIdentifier('ID', 1, 24, 'Type'), ] const codeElement = container.querySelector('code')! calculator.prepareCodeBlock(codeElement, identifiers) const wrappedElements = container.querySelectorAll('[data-graphql-id]') expect(wrappedElements.length).toBe(4) }) it('should get positions of wrapped identifiers', () => { const container = document.createElement('div') container.innerHTML = ` <pre class="code-block"> <code> <span class="line"><span data-graphql-id="0-user-Field" data-graphql-name="user" data-graphql-kind="Field" data-graphql-start="0" data-graphql-end="4" data-graphql-line="1" data-graphql-column="1" data-graphql-path="user">user</span> {</span> </code> </pre> ` // Mock getBoundingClientRect container.getBoundingClientRect = () => ({ top: 0, left: 0, right: 100, bottom: 100, width: 100, height: 100, x: 0, y: 0, toJSON: () => ({}), }) const userSpan = container.querySelector('[data-graphql-id]')! userSpan.getBoundingClientRect = () => ({ top: 10, left: 20, right: 60, bottom: 30, width: 40, height: 20, x: 20, y: 10, toJSON: () => ({}), }) const positions = calculator.getIdentifierPositions(container) expect(positions.size).toBe(1) const result = positions.get('0-user-Field') expect(result).toBeDefined() expect(result!.position).toEqual({ top: 10, left: 20, width: 40, height: 20, }) expect(result!.identifier.name).toBe('user') expect(result!.identifier.kind).toBe('Field') }) it('should skip already wrapped identifiers', () => { const container = document.createElement('div') container.innerHTML = ` <pre class="code-block"> <code><span data-graphql-id="existing">user</span> {</code> </pre> ` const identifiers = [ createTestIdentifier('user', 1, 1), ] const codeElement = container.querySelector('code')! calculator.prepareCodeBlock(codeElement, identifiers) // Should still only have one wrapped element const wrappedElements = container.querySelectorAll('[data-graphql-id]') expect(wrappedElements.length).toBe(1) expect(wrappedElements[0]!.getAttribute('data-graphql-id')).toBe('existing') }) it('should handle empty lines gracefully', () => { const container = document.createElement('div') container.innerHTML = ` <pre class="code-block"> <code>query { user</code> </pre> ` const identifiers = [ createTestIdentifier('query', 1, 1), createTestIdentifier('user', 3, 3), ] const codeElement = container.querySelector('code')! expect(() => { calculator.prepareCodeBlock(codeElement, identifiers) }).not.toThrow() const wrappedElements = container.querySelectorAll('[data-graphql-id]') expect(wrappedElements.length).toBe(2) }) }) describe('createSimpleOverlay', () => { it('should create positioned overlay element', () => { const position = { top: 10, left: 20, width: 40, height: 20 } const identifier = createTestIdentifier('user', 1, 1) const overlay = createSimpleOverlay(position, identifier) expect(overlay.style.position).toBe('absolute') expect(overlay.style.top).toBe('10px') expect(overlay.style.left).toBe('20px') expect(overlay.style.width).toBe('40px') expect(overlay.style.height).toBe('20px') expect(overlay.style.cursor).toBe('pointer') expect(overlay.getAttribute('data-graphql-overlay')).toBe('true') expect(overlay.getAttribute('data-graphql-name')).toBe('user') expect(overlay.getAttribute('data-graphql-kind')).toBe('Field') }) it('should handle click events', () => { const position = { top: 10, left: 20, width: 40, height: 20 } const identifier = createTestIdentifier('user', 1, 1) let clickedIdentifier: Identifier | null = null const overlay = createSimpleOverlay(position, identifier, { onClick: (id) => { clickedIdentifier = id }, }) // Simulate click const event = new MouseEvent('click') overlay.dispatchEvent(event) expect(clickedIdentifier).toBe(identifier) }) it('should handle hover events', () => { const position = { top: 10, left: 20, width: 40, height: 20 } const identifier = createTestIdentifier('user', 1, 1) let hoveredIdentifier: Identifier | null = null const overlay = createSimpleOverlay(position, identifier, { onHover: (id) => { hoveredIdentifier = id }, }) // Simulate hover const event = new MouseEvent('mouseenter') overlay.dispatchEvent(event) expect(hoveredIdentifier).toBe(identifier) }) it('should apply custom className', () => { const position = { top: 10, left: 20, width: 40, height: 20 } const identifier = createTestIdentifier('user', 1, 1) const overlay = createSimpleOverlay(position, identifier, { className: 'custom-overlay-class', }) expect(overlay.className).toBe('custom-overlay-class') }) }) })