UNPKG

@wdio/image-comparison-core

Version:

Image comparison core module for @wdio/visual-service - WebdriverIO visual testing framework

262 lines (261 loc) 11.9 kB
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { join } from 'node:path'; import logger from '@wdio/logger'; import beforeScreenshot from './beforeScreenshot.js'; import hideScrollBars from '../clientSideScripts/hideScrollbars.js'; import hideRemoveElements from '../clientSideScripts/hideRemoveElements.js'; import setCustomCss from '../clientSideScripts/setCustomCss.js'; import toggleTextTransparency from '../clientSideScripts/toggleTextTransparency.js'; import waitForFonts from '../clientSideScripts/waitForFonts.js'; import { CUSTOM_CSS_ID } from './constants.js'; const log = logger('test'); vi.mock('@wdio/logger', () => import(join(process.cwd(), '__mocks__', '@wdio/logger'))); vi.mock('../methods/instanceData.js', () => ({ default: vi.fn().mockResolvedValue({ appName: 'mocked-app', browserName: 'mocked-browser', devicePixelRatio: 1, isAndroid: false, isIOS: false, isMobile: false, platformName: 'mocked-platform', }) })); describe('beforeScreenshot', () => { let logDebugSpy; let logWarnSpy; const createMockBrowserInstance = (mockExecuteFn = vi.fn().mockResolvedValue(''), customProperties = {}) => { return { execute: mockExecuteFn, ...customProperties }; }; beforeEach(() => { logDebugSpy = vi.spyOn(log, 'debug').mockImplementation(() => { }); logWarnSpy = vi.spyOn(log, 'warn').mockImplementation(() => { }); }); afterEach(() => { vi.clearAllMocks(); logDebugSpy.mockRestore(); logWarnSpy.mockRestore(); }); const baseInstanceData = { appName: 'appName', browserName: 'browserName', browserVersion: 'browserVersion', deviceName: 'deviceName', devicePixelRatio: 1, logName: 'logName', deviceRectangles: { bottomBar: { y: 0, x: 0, width: 0, height: 0 }, homeBar: { x: 0, y: 0, width: 0, height: 0 }, leftSidePadding: { y: 0, x: 0, width: 0, height: 0 }, rightSidePadding: { y: 0, x: 0, width: 0, height: 0 }, screenSize: { height: 1, width: 1 }, statusBar: { x: 0, y: 0, width: 0, height: 0 }, statusBarAndAddressBar: { y: 0, x: 0, width: 0, height: 0 }, viewport: { y: 0, x: 0, width: 0, height: 0 }, }, isAndroid: false, isIOS: false, isMobile: false, name: 'name', nativeWebScreenshot: false, platformName: 'platformName', platformVersion: 'platformVersion', initialDevicePixelRatio: 1, }; const baseOptions = { addressBarShadowPadding: 6, disableBlinkingCursor: false, disableCSSAnimation: false, enableLayoutTesting: false, noScrollBars: false, toolBarShadowPadding: 6, hideElements: [], removeElements: [], waitForFontsLoaded: false, }; const createOptions = (overrides = {}) => ({ instanceData: baseInstanceData, ...baseOptions, ...overrides, }); it('should be able to return the enriched instance data with default options', async () => { const mockBrowserInstance = createMockBrowserInstance(); const options = createOptions(); expect(await beforeScreenshot(mockBrowserInstance, options)).toMatchSnapshot(); }); it('should be able to return the enriched instance data with `addShadowPadding: true`', async () => { const mockBrowserInstance = createMockBrowserInstance(); const options = createOptions({ disableBlinkingCursor: true, disableCSSAnimation: true, noScrollBars: true, hideElements: ['<div></div>'], removeElements: ['<div></div>'], waitForFontsLoaded: true, }); expect(await beforeScreenshot(mockBrowserInstance, options, true)).toMatchSnapshot(); }); it('should handle waitForFontsLoaded functionality', async () => { const mockBrowserInstance = createMockBrowserInstance(); const options = createOptions({ waitForFontsLoaded: true, }); await beforeScreenshot(mockBrowserInstance, options); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(waitForFonts); }); it('should handle waitForFontsLoaded error gracefully and log debug message', async () => { const fontError = new Error('Font load error'); const mockExecute = vi.fn().mockRejectedValue(fontError); const mockBrowserInstance = createMockBrowserInstance(mockExecute); const options = createOptions({ waitForFontsLoaded: true, }); await beforeScreenshot(mockBrowserInstance, options); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(waitForFonts); expect(logDebugSpy).toHaveBeenCalledWith('Waiting for fonts to load threw an error:', fontError); }); it('should handle noScrollBars option', async () => { const mockBrowserInstance = createMockBrowserInstance(); const options = createOptions({ noScrollBars: true, }); await beforeScreenshot(mockBrowserInstance, options); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(hideScrollBars, true); }); it('should handle hide and remove elements', async () => { const mockBrowserInstance = createMockBrowserInstance(); const hideElements = ['<div></div>']; const removeElements = ['<span></span>']; const options = createOptions({ hideElements, removeElements, }); await beforeScreenshot(mockBrowserInstance, options); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(hideRemoveElements, { hide: hideElements, remove: removeElements }, true); }); it('should handle hide/remove elements error gracefully and log warning', async () => { const elementError = new Error('Element not found'); const mockExecute = vi.fn().mockRejectedValue(elementError); const mockBrowserInstance = createMockBrowserInstance(mockExecute); const hideElements = ['<div></div>']; const options = createOptions({ hideElements, }); await beforeScreenshot(mockBrowserInstance, options); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(hideRemoveElements, { hide: hideElements, remove: [] }, true); expect(logWarnSpy.mock.calls[0]).toMatchSnapshot(); }); it('should handle CSS customization for desktop', async () => { const mockBrowserInstance = createMockBrowserInstance(); const options = createOptions({ disableBlinkingCursor: true, disableCSSAnimation: true, addressBarShadowPadding: 10, toolBarShadowPadding: 15, }); await beforeScreenshot(mockBrowserInstance, options); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(setCustomCss, { addressBarPadding: 0, disableBlinkingCursor: true, disableCSSAnimation: true, id: CUSTOM_CSS_ID, toolBarPadding: 0, }); }); it('should handle CSS customization for mobile platform', async () => { const mockBrowserInstance = createMockBrowserInstance(undefined, { isAndroid: true, isIOS: false, isMobile: true }); const options = createOptions({ instanceData: { ...baseInstanceData, platformName: 'Android', isAndroid: true, isMobile: true, }, }); await beforeScreenshot(mockBrowserInstance, options); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(setCustomCss, { addressBarPadding: 0, disableBlinkingCursor: false, disableCSSAnimation: false, id: CUSTOM_CSS_ID, toolBarPadding: 0, }); }); it('should handle layout testing', async () => { const mockBrowserInstance = createMockBrowserInstance(); const options = createOptions({ enableLayoutTesting: true, }); await beforeScreenshot(mockBrowserInstance, options); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(toggleTextTransparency, true); }); it('should handle layout testing with addShadowPadding', async () => { const mockBrowserInstance = createMockBrowserInstance(); const options = createOptions({ enableLayoutTesting: true, instanceData: { ...baseInstanceData, browserName: 'Safari', platformName: 'iOS', isIOS: true, isMobile: true, }, }); await beforeScreenshot(mockBrowserInstance, options, true); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(toggleTextTransparency, true); }); it('should not execute browser commands when no options are enabled', async () => { const mockBrowserInstance = createMockBrowserInstance(); const options = createOptions(); await beforeScreenshot(mockBrowserInstance, options); // Should only call the instanceData mock, no browser execute calls expect(mockBrowserInstance.execute).not.toHaveBeenCalled(); expect(logDebugSpy).not.toHaveBeenCalled(); expect(logWarnSpy).not.toHaveBeenCalled(); }); it('should handle multiple options simultaneously', async () => { const mockBrowserInstance = createMockBrowserInstance(); const hideElements = ['<div></div>']; const options = createOptions({ waitForFontsLoaded: true, noScrollBars: true, hideElements, disableBlinkingCursor: true, enableLayoutTesting: true, }); await beforeScreenshot(mockBrowserInstance, options); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(waitForFonts); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(hideScrollBars, true); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(hideRemoveElements, { hide: hideElements, remove: [] }, true); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(setCustomCss, expect.any(Object)); expect(mockBrowserInstance.execute).toHaveBeenCalledWith(toggleTextTransparency, true); }); it('should handle multiple errors and log both debug and warning messages', async () => { const fontError = new Error('Font load error'); const elementError = new Error('Element not found'); const mockExecute = vi.fn() .mockRejectedValueOnce(fontError) // waitForFonts .mockRejectedValueOnce(elementError); // hideRemoveElements const mockBrowserInstance = createMockBrowserInstance(mockExecute); const options = createOptions({ waitForFontsLoaded: true, hideElements: ['<div></div>'], }); await beforeScreenshot(mockBrowserInstance, options); expect(logDebugSpy).toHaveBeenCalledWith('Waiting for fonts to load threw an error:', fontError); expect(logWarnSpy.mock.calls[0]).toMatchSnapshot(); }); it('should handle custom browser properties when needed', async () => { const mockBrowserInstance = createMockBrowserInstance(undefined, { getWindowSize: vi.fn().mockResolvedValue({ width: 1920, height: 1080 }), getOrientation: vi.fn().mockResolvedValue('LANDSCAPE') }); const options = createOptions(); await beforeScreenshot(mockBrowserInstance, options); expect(mockBrowserInstance.getWindowSize).toBeDefined(); expect(mockBrowserInstance.getOrientation).toBeDefined(); }); });