import { emitEvent } from '../emitEvent'; describe('emitEvent', () => { let mockPostMessage: jest.Mock; beforeEach(() => { mockPostMessage = jest.fn(); // Mock window.parent with postMessage Object.defineProperty(window, 'parent', { value: { postMessage: mockPostMessage }, writable: true, configurable: true }); }); afterEach(() => { jest.clearAllMocks(); jest.restoreAllMocks(); }); describe('basic functionality', () => { it('should call window.parent.postMessage with event name', () => { emitEvent('updateHeight'); expect(mockPostMessage).toHaveBeenCalledTimes(1); expect(mockPostMessage).toHaveBeenCalledWith( { type: 'updateHeight', payload: null }, '*' ); }); it('should send event name as type property', () => { emitEvent('customEvent'); expect(mockPostMessage).toHaveBeenCalledWith( expect.objectContaining({ type: 'customEvent' }), '*' ); }); it('should send wildcard origin for cross-origin communication', () => { emitEvent('testEvent'); const callArgs = mockPostMessage.mock.calls[0]; expect(callArgs[1]).toBe('*'); }); }); describe('data handling', () => { it('should append px to numeric data', () => { emitEvent('updateHeight', 500); expect(mockPostMessage).toHaveBeenCalledWith( { type: 'updateHeight', payload: '500px' }, '*' ); }); it('should set payload to null when data is undefined', () => { emitEvent('testEvent', undefined); expect(mockPostMessage).toHaveBeenCalledWith( { type: 'testEvent', payload: null }, '*' ); }); it('should set payload to null when no data is provided', () => { emitEvent('testEvent'); expect(mockPostMessage).toHaveBeenCalledWith( { type: 'testEvent', payload: null }, '*' ); }); }); describe('window safety', () => { it('should not throw error when window.parent is undefined', () => { Object.defineProperty(window, 'parent', { value: undefined, writable: true, configurable: true }); expect(() => { emitEvent('testEvent'); }).not.toThrow(); }); it('should not call postMessage when window.parent is null', () => { Object.defineProperty(window, 'parent', { value: null, writable: true, configurable: true }); emitEvent('testEvent'); expect(mockPostMessage).not.toHaveBeenCalled(); }); it('should not call postMessage when window.parent does not exist', () => { const newMockPostMessage = jest.fn(); Object.defineProperty(window, 'parent', { value: { postMessage: newMockPostMessage }, writable: true, configurable: true }); // Create a scenario where window.parent is falsy Object.defineProperty(window, 'parent', { value: false, writable: true, configurable: true }); emitEvent('testEvent'); expect(newMockPostMessage).not.toHaveBeenCalled(); }); }); describe('event name variations', () => { it('should handle event names with underscores', () => { emitEvent('update_height'); expect(mockPostMessage).toHaveBeenCalledWith( expect.objectContaining({ type: 'update_height' }), '*' ); }); it('should handle event names with camelCase', () => { emitEvent('updateHeight'); expect(mockPostMessage).toHaveBeenCalledWith( expect.objectContaining({ type: 'updateHeight' }), '*' ); }); it('should handle event names with hyphens', () => { emitEvent('update-height'); expect(mockPostMessage).toHaveBeenCalledWith( expect.objectContaining({ type: 'update-height' }), '*' ); }); it('should handle event names in uppercase', () => { emitEvent('UPDATE_HEIGHT'); expect(mockPostMessage).toHaveBeenCalledWith( expect.objectContaining({ type: 'UPDATE_HEIGHT' }), '*' ); }); it('should handle empty string as event name', () => { emitEvent(''); expect(mockPostMessage).toHaveBeenCalledWith( expect.objectContaining({ type: '' }), '*' ); }); it('should handle very long event names', () => { const longEventName = 'a'.repeat(1000); emitEvent(longEventName); expect(mockPostMessage).toHaveBeenCalledWith( expect.objectContaining({ type: longEventName }), '*' ); }); }); describe('multiple calls', () => { it('should handle multiple sequential events', () => { emitEvent('event1'); emitEvent('event2', 100); emitEvent('event3'); expect(mockPostMessage).toHaveBeenCalledTimes(3); expect(mockPostMessage).toHaveBeenNthCalledWith( 1, { type: 'event1', payload: null }, '*' ); expect(mockPostMessage).toHaveBeenNthCalledWith( 2, { type: 'event2', payload: '100px' }, '*' ); expect(mockPostMessage).toHaveBeenNthCalledWith( 3, { type: 'event3', payload: null }, '*' ); }); it('should handle rapid successive calls', () => { for (let i = 0; i < 10; i++) { emitEvent(`event${i}`, i * 100); } expect(mockPostMessage).toHaveBeenCalledTimes(10); }); }); describe('real-world use cases', () => { it('should emit updateHeight event for cricket scorecard', () => { emitEvent('updateHeight', 500); expect(mockPostMessage).toHaveBeenCalledWith( { type: 'updateHeight', payload: '500px' }, '*' ); }); it('should emit enableButton event for match events', () => { emitEvent('enableButton'); expect(mockPostMessage).toHaveBeenCalledWith( { type: 'enableButton', payload: null }, '*' ); }); it('should emit custom widget ready event', () => { emitEvent('widgetReady', 200); expect(mockPostMessage).toHaveBeenCalledWith( { type: 'widgetReady', payload: '200px' }, '*' ); }); it('should emit multiple events in sequence for complex workflows', () => { emitEvent('initStart'); emitEvent('updateHeight', 400); emitEvent('contentLoaded'); emitEvent('updateHeight', 600); expect(mockPostMessage).toHaveBeenCalledTimes(4); }); }); describe('edge cases', () => { it('should handle negative numbers', () => { emitEvent('updateHeight', -100); expect(mockPostMessage).toHaveBeenCalledWith( { type: 'updateHeight', payload: '-100px' }, '*' ); }); it('should handle very large numbers', () => { emitEvent('updateHeight', 999999999); expect(mockPostMessage).toHaveBeenCalledWith( { type: 'updateHeight', payload: '999999999px' }, '*' ); }); it('should handle float numbers', () => { emitEvent('updateHeight', 100.5); expect(mockPostMessage).toHaveBeenCalledWith( { type: 'updateHeight', payload: '100.5px' }, '*' ); }); it('should handle special characters in event name', () => { emitEvent('event@#$%'); expect(mockPostMessage).toHaveBeenCalledWith( expect.objectContaining({ type: 'event@#$%' }), '*' ); }); }); });