Skip to content

Commit dd71368

Browse files
committed
fix: last fixes for the rounded bottom corners
1 parent 86572b0 commit dd71368

File tree

4 files changed

+116
-221
lines changed

4 files changed

+116
-221
lines changed

packages/image-comparison-core/src/methods/screenshots.ts

Lines changed: 11 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import logger from '@wdio/logger'
2-
import { join } from 'node:path'
3-
import { promises as fsPromises } from 'node:fs'
42
import scrollToPosition from '../clientSideScripts/scrollToPosition.js'
53
import getDocumentScrollHeight from '../clientSideScripts/getDocumentScrollHeight.js'
64
import { calculateDprData, getBase64ScreenshotSize, waitFor } from '../helpers/utils.js'
@@ -15,7 +13,6 @@ import hideRemoveElements from '../clientSideScripts/hideRemoveElements.js'
1513
import hideScrollBars from '../clientSideScripts/hideScrollbars.js'
1614
import type { ElementRectanglesOptions, RectanglesOutput } from './rectangles.interfaces.js'
1715
import { determineElementRectangles } from './rectangles.js'
18-
import { cropAndConvertToDataURL, saveBase64Image } from './images.js'
1916

2017
const log = logger('@wdio/visual-service:@wdio/image-comparison-core:screenshots')
2118

@@ -280,39 +277,23 @@ export async function getDesktopFullPageScreenshotsData(browserInstance:Webdrive
280277
const { devicePixelRatio, fullPageScrollTimeout, hideAfterFirstScroll, innerHeight } = options
281278
let actualInnerHeight = innerHeight
282279

283-
// Detect Safari desktop for debug saving and drop shadow cropping
284280
const { capabilities } = browserInstance
285281
const browserName = (capabilities?.browserName || '').toLowerCase()
286282
const isSafariDesktop = browserName.includes('safari') && !browserInstance.isMobile
287-
const debugDir = isSafariDesktop ? join(process.cwd(), '.tmp', 'debug', 'safari-desktop-fullpage-screenshots') : null
288283

289-
// Safari desktop has a drop shadow at the top
290-
// The drop shadow is always 1 device pixel, which translates to 1 * DPR CSS pixels
291284
const safariTopDropShadowCssPixels = isSafariDesktop ? Math.round(1 * devicePixelRatio) : 0
292-
// For Safari desktop, calculate effective scroll increment
293-
// First image: scroll by 0, use full height (716px)
294-
// Subsequent images: scroll by (actualInnerHeight - dropShadowOffset) = 715px, crop 1px from top
285+
const safariBottomCropOffsetCssPixels = isSafariDesktop ? Math.round(10 * devicePixelRatio) : 0
286+
295287
const effectiveScrollIncrement = isSafariDesktop
296-
? actualInnerHeight - safariTopDropShadowCssPixels
288+
? actualInnerHeight - safariTopDropShadowCssPixels - safariBottomCropOffsetCssPixels
297289
: actualInnerHeight
298290

299-
// Create debug directory if needed
300-
if (debugDir) {
301-
await fsPromises.mkdir(debugDir, { recursive: true })
302-
}
303-
304291
// Start with an empty array, during the scroll it will be filled because a page could also have a lazy loading
305292
const amountOfScrollsArray = []
306293
let scrollHeight: number | undefined
307294
let screenshotSize
308295

309296
for (let i = 0; i <= amountOfScrollsArray.length; i++) {
310-
// Determine and start scrolling
311-
// For Safari desktop: first image scrolls to 0, subsequent images scroll by effectiveScrollIncrement (715px)
312-
// Image 0: scrollY = 0
313-
// Image 1: scrollY = 715 (effectiveScrollIncrement)
314-
// Image 2: scrollY = 1430 (2 * effectiveScrollIncrement)
315-
// etc.
316297
const scrollY = isSafariDesktop
317298
? (i === 0 ? 0 : i * effectiveScrollIncrement)
318299
: actualInnerHeight * i
@@ -344,161 +325,75 @@ export async function getDesktopFullPageScreenshotsData(browserInstance:Webdrive
344325
// and SafariDriver for Safari 11
345326
}
346327

347-
// Determine scroll height and check if we need to scroll again
348328
scrollHeight = await browserInstance.execute(getDocumentScrollHeight)
349329

350-
// For Safari desktop, use effectiveScrollIncrement for the scroll check
351330
const scrollCheckHeight = isSafariDesktop ? effectiveScrollIncrement : actualInnerHeight
352331
if (scrollHeight && (scrollY + scrollCheckHeight < scrollHeight) && screenshotSize.height === actualInnerHeight) {
353332
amountOfScrollsArray.push(amountOfScrollsArray.length)
354333
}
355334
// There is no else, Lazy load and large screenshots,
356335
// like with older drivers such as FF <= 47 and IE11, will not work
357336

358-
// The height of the image of the last 1 could be different
359-
// For Safari desktop, account for first image being full height and subsequent images being cropped
360337
const isFirstImage = i === 0
361338
const isLastImage = amountOfScrollsArray.length === i
362339
let imageHeight: number
363340
if (scrollHeight && isLastImage) {
364341
if (isSafariDesktop) {
365-
// Calculate remaining content: scrollHeight - (firstImageHeight + (numberOfPreviousImages - 1) * effectiveScrollIncrement)
366342
const numberOfPreviousImages = viewportScreenshots.length
367343
const totalPreviousHeight = numberOfPreviousImages === 0
368344
? 0
369345
: actualInnerHeight + (numberOfPreviousImages - 1) * effectiveScrollIncrement
370346
const remainingContent = scrollHeight - totalPreviousHeight
371347

372-
// For the last image, we need to be smart:
373-
// - If remainingContent >= actualInnerHeight: it's a full screenshot, treat it like a regular non-first image
374-
// (crop 1px from top, visible height = 715px)
375-
// - If remainingContent < actualInnerHeight: it's a partial screenshot
376-
// For partial screenshots, we're cropping from a position that doesn't include the drop shadow at pixel 0
377-
// So we don't need to add 1px - just use remainingContent directly
378348
imageHeight = remainingContent >= actualInnerHeight
379-
? effectiveScrollIncrement // Full screenshot: treat like regular non-first image
380-
: remainingContent // Partial screenshot: use remainingContent directly (no drop shadow in cropped region)
349+
? effectiveScrollIncrement + safariBottomCropOffsetCssPixels
350+
: remainingContent + safariBottomCropOffsetCssPixels
381351
} else {
382352
imageHeight = scrollHeight - actualInnerHeight * viewportScreenshots.length
383353
}
384354
} else {
385-
// Non-last images: use full height for first, effectiveScrollIncrement for subsequent
386355
imageHeight = isSafariDesktop && !isFirstImage
387356
? effectiveScrollIncrement
388357
: screenshotSize.height
389358
}
390359

391-
// The starting position for cropping could be different for the last image (0 means no cropping)
392-
// For Safari desktop, crop 1px from top for all images except first
360+
if (isSafariDesktop && isFirstImage && safariBottomCropOffsetCssPixels > 0) {
361+
imageHeight -= safariBottomCropOffsetCssPixels
362+
}
363+
393364
let imageYPosition: number
394365
if (isSafariDesktop) {
395366
if (isLastImage && !isFirstImage) {
396-
// Last image: need to handle two cases
397367
const numberOfPreviousImages = viewportScreenshots.length
398368
const totalPreviousHeight = numberOfPreviousImages === 0
399369
? 0
400370
: actualInnerHeight + (numberOfPreviousImages - 1) * effectiveScrollIncrement
401371
const remainingContent = scrollHeight ? scrollHeight - totalPreviousHeight : 0
402372

403-
// Full screenshot: treat like regular non-first image (crop 1px from top)
404-
// Partial screenshot: we want to show the last remainingContent pixels
405-
// imageHeight = remainingContent, so we start at: 716 - remainingContent
406-
// For partial screenshots, the drop shadow is at pixel 0, but we're cropping from a different position
407-
// so we don't need to crop the drop shadow - just position to get the last remainingContent pixels
408373
imageYPosition = remainingContent >= actualInnerHeight
409374
? safariTopDropShadowCssPixels
410-
: actualInnerHeight - remainingContent
375+
: actualInnerHeight - remainingContent - safariBottomCropOffsetCssPixels
411376
} else if (!isFirstImage) {
412-
// Non-last, non-first images: crop 1px from top
413377
imageYPosition = safariTopDropShadowCssPixels
414378
} else {
415-
// First image: no crop
416379
imageYPosition = 0
417380
}
418381
} else {
419-
// Non-Safari: standard calculation
420382
imageYPosition = isLastImage && !isFirstImage
421383
? actualInnerHeight - imageHeight
422384
: 0
423385
}
424386

425-
// Debug logging for Safari desktop to see what's being cropped
426-
if (isSafariDesktop) {
427-
// For non-first images, imageHeight already accounts for the crop, so visible = imageHeight
428-
// For first image, visible = imageHeight (no crop)
429-
const visibleHeightAfterCrop = imageHeight
430-
console.log(`Safari desktop screenshot ${i} cropping details:`, {
431-
isFirstImage,
432-
isLastImage,
433-
scrollY,
434-
screenshotSize: {
435-
width: screenshotSize.width,
436-
height: screenshotSize.height,
437-
},
438-
imageHeight,
439-
imageYPosition,
440-
visibleHeightAfterCrop,
441-
actualInnerHeight,
442-
effectiveScrollIncrement,
443-
remainingContent: isLastImage && scrollHeight
444-
? (() => {
445-
const numberOfPreviousImages = viewportScreenshots.length
446-
const totalPreviousHeight = numberOfPreviousImages === 0
447-
? 0
448-
: actualInnerHeight + (numberOfPreviousImages - 1) * effectiveScrollIncrement
449-
return scrollHeight - totalPreviousHeight
450-
})()
451-
: undefined,
452-
cropFromOriginal: {
453-
startY: imageYPosition,
454-
height: imageHeight,
455-
endY: imageYPosition + imageHeight,
456-
},
457-
})
458-
}
459-
460-
// Calculate canvasYPosition for stitching
461-
// For Safari desktop: first image at 0, subsequent images start where previous image ends
462387
let canvasYPosition: number
463388
if (isSafariDesktop && !isFirstImage) {
464-
// Calculate based on where the previous image ends
465-
// Previous image's canvasYPosition + previous image's height
466389
const previousImage = viewportScreenshots[viewportScreenshots.length - 1]
467390
canvasYPosition = previousImage
468391
? previousImage.canvasYPosition + previousImage.imageHeight
469-
: actualInnerHeight + (i - 1) * effectiveScrollIncrement // Fallback (shouldn't happen)
392+
: actualInnerHeight + (i - 1) * effectiveScrollIncrement
470393
} else {
471394
canvasYPosition = isSafariDesktop ? 0 : scrollY
472395
}
473396

474-
// Calculate crop dimensions in device pixels for debug saving
475-
const imageXPositionDevicePixels = 0
476-
const imageYPositionDevicePixels = Math.round(imageYPosition * devicePixelRatio)
477-
const imageWidthDevicePixels = Math.round(screenshotSize.width * devicePixelRatio)
478-
const imageHeightDevicePixels = Math.round(imageHeight * devicePixelRatio)
479-
480-
// Save cropped screenshot to debug folder for Safari desktop
481-
if (isSafariDesktop && debugDir) {
482-
try {
483-
const croppedBase64 = await cropAndConvertToDataURL({
484-
addIOSBezelCorners: false,
485-
base64Image: screenshot,
486-
deviceName: '',
487-
devicePixelRatio: 1, // Already in device pixels
488-
height: imageHeightDevicePixels,
489-
isIOS: false,
490-
isLandscape: false,
491-
sourceX: imageXPositionDevicePixels,
492-
sourceY: imageYPositionDevicePixels,
493-
width: imageWidthDevicePixels,
494-
})
495-
const debugFilePath = join(debugDir, `step-${i}-scrollY-${scrollY}-height-${imageHeight}-yPos-${imageYPosition}.png`)
496-
await saveBase64Image(croppedBase64, debugFilePath)
497-
} catch (error) {
498-
log.warn(`Failed to save debug screenshot for step ${i}:`, error)
499-
}
500-
}
501-
502397
// Store all the screenshot data in the screenshot object
503398
viewportScreenshots.push({
504399
...calculateDprData(

0 commit comments

Comments
 (0)