Last active
December 18, 2023 18:40
-
-
Save edumserrano/5e878002c7dfb40d3126e28dbb29dd42 to your computer and use it in GitHub Desktop.
Playwright clean up obsolete snapshots
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This script detects obsolete Playwright snapshots and automatically removes them. | |
| # Obsolete snapshots are detected by re-generating the snapshots in a different folder and then | |
| # comparing these two folders. | |
| # To do this, we are taking advantage of the fact that development/pipeline snapshots | |
| # are created using a Linux docker container, as we can re-generate the Playwright snapshots using | |
| # the locally-installed version to have them automatically created in a separate folder (i.e. `linux` vs `windows`). | |
| # | |
| # This script will be required so long as Playwright does not have built-in functionality to detect and clean up | |
| # obsolete snapshots. | |
| # See: https://github.com/microsoft/playwright/issues/16582 | |
| # | |
| # To run this script without removing an unused/obsolete snapshots and without removing the expected | |
| # snapshots directory, please use the -dryRun parameter. | |
| param( | |
| [string] $actualPath = "./tests/_snapshots/linux", | |
| [string] $expectedPath = "./tests/_snapshots/win32", | |
| [int] $maxAttempts = 5, | |
| [string] $dryRun = "no" | |
| ) | |
| function Convert2Bool($this) | |
| { | |
| return ($("False","0","","N","No",'$False',"Off") -notcontains [string]$this) | |
| } | |
| function EnforceWindowsOnlyExecution | |
| { | |
| if(-not $IsWindows) | |
| { | |
| Write-Host -ForegroundColor Red "❌ This script can only be executed on Windows."; | |
| exit 1; | |
| } | |
| } | |
| function GenerateExpectedSnapshots([int] $maxAttempts) | |
| { | |
| # Run Playwright to generate the expected snapshots | |
| $divider = "`n-------------------------------`n" | |
| Write-Host "$divider"; | |
| $runTestsCommand = "npx playwright test --update-snapshots"; | |
| $attemptsCount = 0; | |
| do | |
| { | |
| $attemptsCount++; | |
| Write-Host "Generating expected snapshots (attempt ${attemptsCount} / $maxAttempts)"; | |
| Invoke-Expression -Command $runTestsCommand; | |
| } until ($LASTEXITCODE -eq 0 -or $attemptsCount -ge $maxAttempts); | |
| Write-Host "$divider"; | |
| # Check if all attempts have failed | |
| if($LASTEXITCODE -ne 0) | |
| { | |
| Write-Host -ForegroundColor Red "❌ Failed to generate the expected snapshots after $attemptsCount attempts."; | |
| exit 1; | |
| } | |
| } | |
| function RemoveObsoleteSnapshots( | |
| [string] $actualPath, | |
| [string] $expectedPath, | |
| [bool] $dryRun) | |
| { | |
| # Determine which files are unused | |
| Write-Host "Searching for unused snapshots" | |
| $actualContents = Get-ChildItem -Recurse -File -Path "$actualPath"; | |
| $expectedContents = Get-ChildItem -Recurse -File -Path "$expectedPath"; | |
| $diffResults = @(Compare-Object -PassThru -Property Name -ReferenceObject $expectedContents -DifferenceObject $actualContents); | |
| $hasUnusedSnapshots = $False; | |
| foreach($item in $diffResults) | |
| { | |
| # Reference Only <= | |
| # Difference Only => | |
| if($item.SideIndicator -ne "=>") | |
| { | |
| continue; | |
| } | |
| # This file is an unused file (difference only) | |
| $fileFullPath = $item | Select-Object -ExpandProperty FullName; | |
| $fileRelativePath = $fileFullPath | Resolve-Path -Relative; | |
| $hasUnusedSnapshots = $True; | |
| if($dryRun) | |
| { | |
| Write-Host "* Unused snapshot detected: ${fileRelativePath}"; | |
| continue; | |
| } | |
| Write-Host "* Deleting unused snapshot: ${fileRelativePath}"; | |
| Remove-Item -Path $fileFullPath | |
| } | |
| if(-not $hasUnusedSnapshots) | |
| { | |
| Write-Host -ForegroundColor Yellow "No unused snapshots detected!"; | |
| } | |
| } | |
| function RemoveEmptyDirectories( | |
| [string] $actualPath, | |
| [bool] $dryRun) | |
| { | |
| if($dryRun) { | |
| Write-Host "Keeping empty directories (-dryRun specified)"; | |
| return; | |
| } | |
| # Check if there are any empty folders and remove them | |
| Write-Host "Removing empty directories" | |
| Get-ChildItem $actualPath -Recurse -Force -Directory | | |
| Sort-Object -Property FullName -Descending | | |
| Where-Object { $($_ | Get-ChildItem -Force | Select-Object -First 1).Count -eq 0 } | | |
| Remove-Item; | |
| } | |
| function RemoveExpectedSnapshotsDirectory([string] $expectedPath) | |
| { | |
| $expectedDirectoryExists = Test-Path -PathType Container -Path $expectedPath | |
| if(-not $expectedDirectoryExists) | |
| { | |
| Write-Host -ForegroundColor Yellow "Expected snapshots directory does not exist, skipping removal"; | |
| return; | |
| } | |
| # Remove the expected snapshots directory | |
| Write-Host "Removing expected snapshots directory"; | |
| Remove-Item -Recurse -Path $expectedPath; | |
| } | |
| function Main | |
| { | |
| $ErrorActionPreference = 'Stop' | |
| $dryRunAsBool = Convert2Bool($dryRun); | |
| EnforceWindowsOnlyExecution; | |
| RemoveExpectedSnapshotsDirectory -expectedPath $expectedPath; # Clean expected folder before starting | |
| GenerateExpectedSnapshots -maxAttempts $maxAttempts; | |
| RemoveObsoleteSnapshots -actualPath $actualPath -expectedPath $expectedPath -dryRun $dryRunAsBool; | |
| RemoveEmptyDirectories -actualPath $actualPath -dryRun $dryRunAsBool; # Remove empty directories in the $actualPath folder | |
| RemoveExpectedSnapshotsDirectory -expectedPath $expectedPath; # Also clean expected folder after completion | |
| Write-Host -ForegroundColor Green "✅ Finished cleaning playwright snapshots"; | |
| } | |
| Main; |
Author
Author
Thank you @brodie124 for developing the above . Just sharing his work 👏
Author
I've decided to improve the initial version of this script. I created the edumserrano/playwright-adventures repo to share some of the experiences I've had whilst using Playwright and one of them is a solution to deleting stale snapshots.
Check out the stale-screenshots-cleanup demo.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This gist relies on the fact that for my setup the tests run via Docker and the
snapshotPathTemplateonplaywright.config.tsis set as:What this means is that when I run my tests normally using Docker all the snapshots are created in a
{testDir}/_snapshots/Linuxfolder and when I run the above script, because I'm using a Windows OS, the snapshots get created at a{testDir}/_snapshots/wind32.The
linuxdirectory is then used as theactualPathon the script and thewin32dir is used as theexpectedPathwhen doing the diff.