@@ -173,6 +173,118 @@ It 'builds the launcher arg string with the script path quoted' {
173173 ShouldBeTrue ($a -match ' -File "C:\\Users\\x\\AppData\\Local\\SnipIT\\SnipIT.ps1"' )
174174}
175175
176+ Describe ' Resolve-SaveImagePath'
177+ It ' keeps a valid PNG path unchanged' {
178+ ShouldBe (Resolve-SaveImagePath - Path ' /tmp/a.png' - FilterFormat ' Png' ) ' /tmp/a.png'
179+ }
180+ It ' keeps a valid JPG path unchanged even when filter is PNG' {
181+ # User explicitly typed .jpg — respect their extension.
182+ ShouldBe (Resolve-SaveImagePath - Path ' /tmp/a.jpg' - FilterFormat ' Png' ) ' /tmp/a.jpg'
183+ }
184+ It ' keeps a .jpeg extension (both supported jpeg forms)' {
185+ ShouldBe (Resolve-SaveImagePath - Path ' /tmp/a.jpeg' - FilterFormat ' Jpeg' ) ' /tmp/a.jpeg'
186+ }
187+ It ' forces a non-image extension to match the PNG filter' {
188+ $p = Resolve-SaveImagePath - Path ' /tmp/a.txt' - FilterFormat ' Png'
189+ ShouldBeTrue ($p.EndsWith (' a.png' ))
190+ }
191+ It ' forces a non-image extension to match the JPEG filter' {
192+ $p = Resolve-SaveImagePath - Path ' /tmp/a.txt' - FilterFormat ' Jpeg'
193+ ShouldBeTrue ($p.EndsWith (' a.jpg' ))
194+ }
195+ It ' forces a non-image extension to match the BMP filter' {
196+ $p = Resolve-SaveImagePath - Path ' /tmp/a.txt' - FilterFormat ' Bmp'
197+ ShouldBeTrue ($p.EndsWith (' a.bmp' ))
198+ }
199+ It ' appends the filter extension when path has no extension' {
200+ $p = Resolve-SaveImagePath - Path ' /tmp/a' - FilterFormat ' Png'
201+ ShouldBeTrue ($p.EndsWith (' a.png' ))
202+ }
203+ It ' preserves the directory component when correcting extension' {
204+ $p = Resolve-SaveImagePath - Path ' /tmp/sub/foo.txt' - FilterFormat ' Bmp'
205+ ShouldBeTrue ($p.EndsWith (' foo.bmp' ))
206+ ShouldBeTrue ($p -like ' *sub*foo.bmp' )
207+ }
208+ It ' is case-insensitive for extension recognition' {
209+ ShouldBe (Resolve-SaveImagePath - Path ' /tmp/a.PNG' - FilterFormat ' Jpeg' ) ' /tmp/a.PNG'
210+ }
211+
212+ Describe ' Get-TrimmedRecent'
213+ It ' returns the input unchanged when under the cap' {
214+ $r = Get-TrimmedRecent - Items @ (' c' , ' b' , ' a' ) - MaxDepth 10
215+ ShouldBe $r.Count 3
216+ ShouldBe $r [0 ] ' c'
217+ }
218+ It ' trims to the top N most recent when over cap' {
219+ $items = 1 .. 20 # 20 is top (most recent) by Stack.ToArray() convention
220+ $r = Get-TrimmedRecent - Items $items - MaxDepth 5
221+ ShouldBe $r.Count 5
222+ ShouldBe $r [0 ] 1 # top-first ordering preserved
223+ ShouldBe $r [4 ] 5
224+ }
225+ It ' returns empty array for null input' {
226+ $r = Get-TrimmedRecent - Items $null
227+ ShouldBe $r.Count 0
228+ }
229+ It ' handles empty array' {
230+ $r = Get-TrimmedRecent - Items @ () - MaxDepth 5
231+ ShouldBe $r.Count 0
232+ }
233+ It ' exactly-at-cap returns the whole set' {
234+ $r = Get-TrimmedRecent - Items (1 .. 100 ) - MaxDepth 100
235+ ShouldBe $r.Count 100
236+ }
237+
238+ Describe ' Get-LoupePosition flip margins'
239+ It ' uses custom FlipMarginX when near right edge' {
240+ $p = Get-LoupePosition - MouseX 1900 - MouseY 100 `
241+ - VsX 0 - VsY 0 - VsWidth 1920 - VsHeight 1080 `
242+ - LoupeWidth 170 - LoupeHeight 190 - FlipMarginX 20
243+ # After flip: X = MouseX - LoupeWidth - FlipMarginX = 1900 - 170 - 20 = 1710
244+ ShouldBe $p.X 1710
245+ }
246+ It ' uses custom FlipMarginY when near bottom edge' {
247+ $p = Get-LoupePosition - MouseX 100 - MouseY 1070 `
248+ - VsX 0 - VsY 0 - VsWidth 1920 - VsHeight 1080 `
249+ - LoupeWidth 170 - LoupeHeight 190 - FlipMarginY 25
250+ # After flip: Y = MouseY - LoupeHeight - FlipMarginY = 1070 - 190 - 25 = 855
251+ ShouldBe $p.Y 855
252+ }
253+ It ' does not flip when loupe fits comfortably' {
254+ $p = Get-LoupePosition - MouseX 500 - MouseY 500 `
255+ - VsX 0 - VsY 0 - VsWidth 1920 - VsHeight 1080
256+ ShouldBe $p.X 524
257+ ShouldBe $p.Y 524
258+ }
259+
260+ Describe ' Get-ImageFormatNameFromPath extra'
261+ It ' recognises uppercase .BMP' { ShouldBe (Get-ImageFormatNameFromPath ' x.BMP' ) ' Bmp' }
262+ It ' defaults .tiff to Png (unsupported)' { ShouldBe (Get-ImageFormatNameFromPath ' x.tiff' ) ' Png' }
263+ It ' handles dot-prefixed hidden filenames' { ShouldBe (Get-ImageFormatNameFromPath ' .hidden.jpg' ) ' Jpeg' }
264+
265+ Describe ' Test-CaptureRectValid edge'
266+ It ' accepts the exact MinSize boundary' {
267+ ShouldBeTrue (Test-CaptureRectValid - Width 2 - Height 2 - MinSize 2 )
268+ }
269+ It ' rejects width just below MinSize' {
270+ ShouldBeFalse (Test-CaptureRectValid - Width 1 - Height 2 - MinSize 2 )
271+ }
272+ It ' rejects negative dimensions' {
273+ ShouldBeFalse (Test-CaptureRectValid - Width -5 - Height 10 )
274+ }
275+
276+ Describe ' Get-CropBounds DPI scenarios'
277+ It ' maps a non-zero-origin viewport (laptop + 4K right monitor)' {
278+ # Virtual screen: X=0, Y=0 across both; user clicks on right monitor at (2500, 800)
279+ $b = Get-CropBounds - RectX 2500 - RectY 800 - RectW 400 - RectH 300 - VsX 0 - VsY 0
280+ ShouldBe $b.X 2500 ; ShouldBe $b.Y 800
281+ ShouldBe $b.Width 400 ; ShouldBe $b.Height 300
282+ }
283+ It ' maps when virtual screen starts below zero (top monitor above primary)' {
284+ $b = Get-CropBounds - RectX 100 - RectY -200 - RectW 50 - RectH 50 - VsX 0 - VsY -1080
285+ ShouldBe $b.X 100 ; ShouldBe $b.Y 880
286+ }
287+
176288Write-Host " "
177289$total = $script :Pass + $script :Fail
178290$color = if ($script :Fail -eq 0 ) { ' Green' } else { ' Red' }
0 commit comments