import { fireEvent, render, waitFor } from '@testing-library/react-native'; import { DeviceEventEmitter, LayoutChangeEvent, Platform, Text, View, } from 'react-native'; import WebView from 'react-native-webview'; import Logger from '../../core/logging/logger'; import { CSWebView } from '../../webview/CSWebView.android'; import { injectWebView, removeWebViewInjection } from '../../webview/webView'; jest.mock('../../core/logging/logger', () => ({ error: jest.fn(), warn: jest.fn(), })); jest.mock('../../webview/webView', () => ({ injectWebView: jest.fn(), removeWebViewInjection: jest.fn(), })); jest.mock('react-native-webview', () => ({ __esModule: true, default: 'WebView', })); describe('CSWebView', () => { beforeEach(() => { Platform.OS = 'android'; jest.clearAllMocks(); }); afterEach(() => { jest.restoreAllMocks(); jest.restoreAllMocks(); }); describe('Implementation 2: Child WebView', () => { it('should render a child webview with the correct props', () => { const mockOnLayout = jest.fn(); const { getByTestId } = render( ); const childWebView = getByTestId('child-webview'); expect(childWebView).toBeTruthy(); }); it('should log an error if more than one child is passed', () => { render( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - Testing with multiple children ); expect(Logger.error).toHaveBeenCalledWith( 'CSWebView component expects exactly 1 child, but received multiple. Ensure that only a single child element is passed' ); }); it('should inject webview on layout', () => { const mockEvent = { nativeEvent: { target: 123 }, } as unknown as LayoutChangeEvent; const { getByTestId } = render( ); const childWebView = getByTestId('child-webview'); fireEvent(childWebView, 'layout', mockEvent); expect(injectWebView).toHaveBeenCalledWith(123); }); it('should call onLayout prop from children', () => { const mockOnLayout = jest.fn(); const { getByTestId } = render( ); const childWebView = getByTestId('child-webview'); fireEvent(childWebView, 'layout', { nativeEvent: { layout: { width: 100, height: 100 } }, }); expect(mockOnLayout).toHaveBeenCalled(); }); it('should set applicationNameForUserAgent to "CS_WebView" when no original applicationNameForUserAgent is provided', () => { const { getByTestId } = render( ); const webView = getByTestId('webview'); expect(webView.props.applicationNameForUserAgent).toContain('CS_WebView'); }); it('should append "CS_WebView" to existing userAgent', () => { const originalUserAgent = 'Mozilla/5.0 (Linux; Android 10; SM-G975F)'; const { getByTestId } = render( ); const webView = getByTestId('webview'); expect(webView.props.applicationNameForUserAgent).toContain(`${originalUserAgent} CS_WebView`); }); it('should work with empty string applicationNameForUserAgent', () => { const { getByTestId } = render( ); const webView = getByTestId('webview'); expect(webView.props.applicationNameForUserAgent).toContain('CS_WebView'); }); it('should work with undefined userAgent', () => { const { getByTestId } = render( ); const webView = getByTestId('webview'); expect(webView.props.applicationNameForUserAgent).toContain('CS_WebView'); }); }); it('should remove onCSWebViewInjectedListener on unmount', () => { const mockRenderWebView = jest.fn((onLayout, webViewUrl) => ( {webViewUrl} )); const removeListener = jest.fn(); jest.spyOn(DeviceEventEmitter, 'addListener').mockImplementation(() => ({ remove: removeListener, })); const { unmount } = render( ); unmount(); expect(removeListener).toHaveBeenCalled(); }); it('should call removeWebViewInjection on unmount', async () => { const { getByTestId, unmount } = render( ); const childWebView = getByTestId('child-webview'); fireEvent(childWebView, 'layout', { nativeEvent: { layout: { width: 100, height: 100 }, target: 123 }, }); await waitFor(() => expect(injectWebView).toHaveBeenCalledWith(123)); DeviceEventEmitter.emit('onCSWebViewInjected'); unmount(); await waitFor(() => expect(removeWebViewInjection).toHaveBeenCalled()); }); });