import os from PIL import Image, ImageChops, ImageStat from appium.webdriver.common.touch_action import TouchAction from pixelmatch.contrib.PIL import pixelmatch def are_images_equal(img1, img2): return True if ImageChops.difference(img1, img2).getbbox() is None else False def images_diff(i1, i2): pairs = zip(i1.getdata(), i2.getdata()) dif = sum(abs(c1 - c2) for p1, p2 in pairs for c1, c2 in zip(p1, p2)) ncomponents = i1.size[0] * i1.size[1] * 3 return (dif / 255.0 * 100) / ncomponents def validate_pixel_match(driver, screenshot_for_comparing: str, threshold: int = 25000) -> None: # Define paths screenshot_dir = os.path.join(os.path.dirname(__file__), "../../../screenshots_for_pixel_match/") os.makedirs(screenshot_dir, exist_ok=True) current_state_screenshot_path = os.path.join(screenshot_dir, "current_state_screenshot.png") driver.save_screenshot(current_state_screenshot_path) # Open images img_1 = Image.open(current_state_screenshot_path) img_2 = Image.open(screenshot_for_comparing) # Check for dimension mismatch if img_1.size != img_2.size: raise ValueError("Images have different dimensions and can't be compared!") # Compare images img_diff = Image.new("RGBA", img_1.size) mismatch = pixelmatch(img_1, img_2, img_diff, includeAA=True) # Save images and difference if mismatch exceeds threshold if mismatch >= threshold: print(f"Mismatch is {mismatch}") diff_save_path = os.path.join(screenshot_dir, "pixel_match_diff.png") img_2_save_path = os.path.join(screenshot_dir, "screenshot_for_comparing.png") img_diff.save(diff_save_path) img_2.save(img_2_save_path) raise ValueError(f"Images are different. Diff image saved to {diff_save_path}") def scroll_page(driver, start_x, start_y, end_x, end_y, duration=1000): """A basic scroll function using touch actions.""" action = TouchAction(driver) action.press(x=start_x, y=start_y).wait(duration).move_to(x=end_x, y=end_y).release().perform() def capture_full_screenshot_native(driver): screen_width = driver.get_window_size()['width'] screen_height = driver.get_window_size()['height'] parts = [] while True: # Capture screenshot driver.save_screenshot("/Users/ivladymyrov-mb/Documents/apollo-go-mobile-automation/screenshots_for_pixel_match/temp_screenshot.png") import time time.sleep(1) # Wait for a second screenshot = Image.open("/Users/ivladymyrov-mb/Documents/apollo-go-mobile-automation/screenshots_for_pixel_match/temp_screenshot.png") parts.append(screenshot) # Smooth scroll driver.execute_script("mobile: scroll", {"direction": "down"}) # Stopping condition: If the new screenshot looks very much like the last one, we might be at the end. # For this, you can use a pixel comparison or other methods. if len(parts) > 1 and images_are_similar(parts[-2], parts[-1]): break # Stitching total_height = len(parts) * screen_height stitched_image = Image.new('RGB', (screen_width, total_height)) offset = 0 for part in parts: stitched_image.paste(part, (0, offset)) offset += screen_height stitched_image.save("/Users/ivladymyrov-mb/Documents/apollo-go-mobile-automation/screenshots_for_pixel_match/stitched_screenshot_native.png") return stitched_image def images_are_similar(img1, img2, threshold=5): # A simple method to compare two images. Threshold is a small value; adjust as needed. diff = ImageChops.difference(img1, img2) stat = ImageStat.Stat(diff) return sum(stat.mean) < threshold