@@ -249,6 +249,52 @@ async function expectCenterAndPreviewEmpty(page, row, column) {
249249 expect ( await previewCellHasPaint ( page , row , column ) ) . toBe ( false ) ;
250250}
251251
252+ async function gridDimensionMetrics ( page ) {
253+ return page . locator ( "[data-sprites-pixel-grid]" ) . evaluate ( ( grid ) => {
254+ const cells = Array . from ( grid . querySelectorAll ( "[role='gridcell']" ) ) ;
255+ const gridRect = grid . getBoundingClientRect ( ) ;
256+ let maxRight = 0 ;
257+ let maxBottom = 0 ;
258+ const styles = getComputedStyle ( grid ) ;
259+ const templateTrackCount = ( value ) => value . split ( " " ) . filter ( Boolean ) . length ;
260+
261+ for ( const cell of cells ) {
262+ const rect = cell . getBoundingClientRect ( ) ;
263+ maxRight = Math . max ( maxRight , rect . right ) ;
264+ maxBottom = Math . max ( maxBottom , rect . bottom ) ;
265+ }
266+
267+ const lastRowCells = cells . slice ( - Number ( grid . dataset . spritesGridSize || 0 ) ) ;
268+ return {
269+ cellCount : cells . length ,
270+ columnCount : templateTrackCount ( styles . gridTemplateColumns ) ,
271+ heightDelta : Math . abs ( maxBottom - gridRect . bottom ) ,
272+ lastCellColumn : cells . at ( - 1 ) ?. dataset . spritePixelColumn || "" ,
273+ lastCellRow : cells . at ( - 1 ) ?. dataset . spritePixelRow || "" ,
274+ lastRowCellCount : lastRowCells . length ,
275+ lastRowColumns : lastRowCells . map ( ( cell ) => cell . dataset . spritePixelColumn ) ,
276+ lastRowRows : lastRowCells . map ( ( cell ) => cell . dataset . spritePixelRow ) ,
277+ rowCount : templateTrackCount ( styles . gridTemplateRows ) ,
278+ widthDelta : Math . abs ( maxRight - gridRect . right ) ,
279+ } ;
280+ } ) ;
281+ }
282+
283+ async function expectExactGridDimensions ( page , expectedSize ) {
284+ await expect ( page . locator ( "[data-sprites-pixel-grid] [role='gridcell']" ) ) . toHaveCount ( expectedSize * expectedSize ) ;
285+ const metrics = await gridDimensionMetrics ( page ) ;
286+ expect ( metrics . cellCount ) . toBe ( expectedSize * expectedSize ) ;
287+ expect ( metrics . columnCount ) . toBe ( expectedSize ) ;
288+ expect ( metrics . rowCount ) . toBe ( expectedSize ) ;
289+ expect ( metrics . lastRowCellCount ) . toBe ( expectedSize ) ;
290+ expect ( metrics . lastCellRow ) . toBe ( String ( expectedSize ) ) ;
291+ expect ( metrics . lastCellColumn ) . toBe ( String ( expectedSize ) ) ;
292+ expect ( metrics . lastRowRows . every ( ( row ) => row === String ( expectedSize ) ) ) . toBe ( true ) ;
293+ expect ( metrics . lastRowColumns ) . toEqual ( Array . from ( { length : expectedSize } , ( _ , index ) => String ( index + 1 ) ) ) ;
294+ expect ( metrics . widthDelta ) . toBeLessThanOrEqual ( 1 ) ;
295+ expect ( metrics . heightDelta ) . toBeLessThanOrEqual ( 1 ) ;
296+ }
297+
252298test ( "Sprite Creator shell loads with visible tool, canvas, details, and status regions" , async ( { page } ) => {
253299 const server = await startSpriteShellTestServer ( ) ;
254300 const failures = collectPageFailures ( page ) ;
@@ -418,6 +464,34 @@ test("Sprite Creator shell loads with visible tool, canvas, details, and status
418464 }
419465} ) ;
420466
467+ test ( "Sprite Creator canvas grid dimensions stay exact across modes and zoom" , async ( { page } ) => {
468+ const server = await startSpriteShellTestServer ( ) ;
469+ const failures = collectPageFailures ( page ) ;
470+
471+ try {
472+ await page . goto ( `${ server . baseUrl } /toolbox/sprites/index.html` , { waitUntil : "networkidle" } ) ;
473+
474+ await expectExactGridDimensions ( page , 16 ) ;
475+ for ( const zoomLabel of [ "200%" , "400%" , "100%" ] ) {
476+ await page . getByRole ( "button" , { name : zoomLabel } ) . click ( ) ;
477+ await expectExactGridDimensions ( page , 16 ) ;
478+ }
479+
480+ await page . getByRole ( "button" , { name : "32x32" } ) . click ( ) ;
481+ await expectExactGridDimensions ( page , 32 ) ;
482+ for ( const zoomLabel of [ "200%" , "400%" , "100%" ] ) {
483+ await page . getByRole ( "button" , { name : zoomLabel } ) . click ( ) ;
484+ await expectExactGridDimensions ( page , 32 ) ;
485+ }
486+
487+ expect ( failures . failedRequests ) . toEqual ( [ ] ) ;
488+ expect ( failures . pageErrors ) . toEqual ( [ ] ) ;
489+ expect ( failures . consoleErrors ) . toEqual ( [ ] ) ;
490+ } finally {
491+ await server . close ( ) ;
492+ }
493+ } ) ;
494+
421495test ( "Sprite Creator keeps center canvas and right preview in sync" , async ( { page } ) => {
422496 const server = await startSpriteShellTestServer ( ) ;
423497 const failures = collectPageFailures ( page ) ;
0 commit comments