import { fireEvent, render, waitFor } from '@testing-library/react-native';
import { Platform, View } from 'react-native';
import WebView from 'react-native-webview';
import { WebViewNavigationEvent } from 'react-native-webview/lib/RNCWebViewNativeComponent';
import Logger from '../../core/logging/logger';
import { CSWebView } from '../../webview/CSWebView.ios';
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 = 'ios';
jest.clearAllMocks();
jest.resetAllMocks();
});
describe('Implementation 2: Child WebView', () => {
const mockOnLoadEnd = jest.fn();
it('should render a child webview with the correct props', () => {
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 load end', () => {
const mockEvent = {
nativeEvent: { target: 123 },
} as unknown as WebViewNavigationEvent;
const { getByTestId } = render(
);
const childWebView = getByTestId('child-webview');
fireEvent(childWebView, 'loadEnd', mockEvent);
expect(injectWebView).toHaveBeenCalledWith(123);
});
it('should call onLoadEnd prop from children', () => {
const { getByTestId } = render(
);
const webView = getByTestId('webview');
fireEvent(webView, 'loadEnd', { nativeEvent: { target: 123 } });
expect(mockOnLoadEnd).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 (iPhone; CPU iPhone OS 16_0 like Mac OS X)';
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 null applicationNameForUserAgent', () => {
const { getByTestId } = render(
);
const webView = getByTestId('webview');
expect(webView.props.applicationNameForUserAgent).toContain('CS_WebView');
});
});
it('should call removeWebViewInjection on unmount', async () => {
const { getByTestId, unmount } = render(
);
const childWebView = getByTestId('child-webview');
fireEvent(childWebView, 'loadEnd', {
nativeEvent: { layout: { width: 100, height: 100 }, target: 123 },
});
unmount();
await waitFor(() => expect(removeWebViewInjection).toHaveBeenCalled());
});
});