@@ -1305,6 +1305,74 @@ test.describe("Workspace Manager V2 bootstrap", () => {
13051305 await page . locator ( "#objectVectorStudioV2ShapeLockButton" ) . click ( ) ;
13061306 await expect ( page . locator ( "#objectVectorStudioV2JsonDetails" ) ) . toContainText ( '"locked": true' ) ;
13071307 await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / O K S h a p e r e c t a n g l e - 1 l o c k s e t t o l o c k e d \. / ) ;
1308+ await page . locator ( "#objectVectorStudioV2ShapeLockButton" ) . click ( ) ;
1309+ await expect ( page . locator ( "#objectVectorStudioV2JsonDetails" ) ) . toContainText ( '"locked": false' ) ;
1310+ await expect ( page . locator ( "#objectVectorStudioV2RenderSurface [data-selection-bounds='rectangle-1']" ) ) . toHaveCount ( 1 ) ;
1311+ await expect ( page . locator ( "#objectVectorStudioV2RenderSurface [data-resize-handle]" ) ) . toHaveCount ( 4 ) ;
1312+ await expect ( page . locator ( "#objectVectorStudioV2RenderSurface [data-pivot-origin='rectangle-1']" ) ) . toHaveCount ( 1 ) ;
1313+
1314+ await page . locator ( "#objectVectorStudioV2RenderSurface [data-shape-id='circle-2']" ) . click ( { modifiers : [ "Shift" ] } ) ;
1315+ await expect ( page . locator ( "#objectVectorStudioV2RenderSurface [data-shape-id='rectangle-1']" ) ) . toHaveClass ( / i s - s e l e c t e d / ) ;
1316+ await expect ( page . locator ( "#objectVectorStudioV2RenderSurface [data-shape-id='circle-2']" ) ) . toHaveClass ( / i s - s e l e c t e d / ) ;
1317+ await expect ( page . locator ( "#objectVectorStudioV2SelectedItemVisibility" ) ) . toContainText ( "2 shape selection" ) ;
1318+ await expect ( page . locator ( "#objectVectorStudioV2JsonDetails" ) ) . toContainText ( '"selectedShapeIds"' ) ;
1319+ await page . locator ( "#objectVectorStudioV2RenderSurface [data-shape-id='rectangle-1']" ) . click ( ) ;
1320+ await expect ( page . locator ( "#objectVectorStudioV2ObjectDetails" ) ) . toContainText ( "Rectangle Geometry" ) ;
1321+
1322+ await page . locator ( "#objectVectorStudioV2GridSnapButton" ) . click ( ) ;
1323+ await expect ( page . locator ( "#objectVectorStudioV2GridSnapButton" ) ) . toHaveAttribute ( "aria-pressed" , "true" ) ;
1324+ await page . locator ( "#objectVectorStudioV2MoveXInput" ) . fill ( "13" ) ;
1325+ await page . locator ( "#objectVectorStudioV2MoveYInput" ) . fill ( "7" ) ;
1326+ await page . locator ( "#objectVectorStudioV2MoveShapeButton" ) . click ( ) ;
1327+ await expect ( page . locator ( "#objectVectorStudioV2JsonDetails" ) ) . toContainText ( '"x": 10' ) ;
1328+ await expect ( page . locator ( "#objectVectorStudioV2JsonDetails" ) ) . toContainText ( '"y": 10' ) ;
1329+ await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / O K M o v e d s h a p e r e c t a n g l e - 1 b y 1 0 , 1 0 \. / ) ;
1330+
1331+ await page . locator ( "#objectVectorStudioV2AngleSnapButton" ) . click ( ) ;
1332+ await page . locator ( "#objectVectorStudioV2RotateInput" ) . fill ( "22" ) ;
1333+ await page . locator ( "#objectVectorStudioV2RotateShapeButton" ) . click ( ) ;
1334+ await expect ( page . locator ( "#objectVectorStudioV2JsonDetails" ) ) . toContainText ( '"rotation": 15' ) ;
1335+ await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / O K R o t a t e d s h a p e r e c t a n g l e - 1 b y 1 5 d e g r e e s \. / ) ;
1336+
1337+ await page . locator ( "#objectVectorStudioV2ScaleInput" ) . fill ( "0" ) ;
1338+ await page . locator ( "#objectVectorStudioV2ScaleShapeButton" ) . click ( ) ;
1339+ await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / F A I L I n v a l i d t r a n s f o r m r e j e c t e d f o r s h a p e r e c t a n g l e - 1 : s c a l e m u s t b e g r e a t e r t h a n 0 \. / ) ;
1340+ await expect ( page . locator ( "#objectVectorStudioV2JsonDetails" ) ) . not . toContainText ( '"scaleX": 0' ) ;
1341+ await page . locator ( "#objectVectorStudioV2ScaleInput" ) . fill ( "1.2" ) ;
1342+ await page . locator ( "#objectVectorStudioV2ScaleShapeButton" ) . click ( ) ;
1343+ await expect ( page . locator ( "#objectVectorStudioV2JsonDetails" ) ) . toContainText ( '"scaleX": 1.2' ) ;
1344+ await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / O K S c a l e d s h a p e r e c t a n g l e - 1 b y 1 \. 2 \. / ) ;
1345+
1346+ await page . locator ( "#objectVectorStudioV2ResizeInput" ) . fill ( "5" ) ;
1347+ await page . locator ( "#objectVectorStudioV2ResizeShapeButton" ) . click ( ) ;
1348+ await expect ( page . locator ( "#objectVectorStudioV2JsonDetails" ) ) . toContainText ( '"width": 91' ) ;
1349+ await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / O K R e s i z e d s h a p e r e c t a n g l e - 1 b y 5 \. / ) ;
1350+
1351+ await page . locator ( "#objectVectorStudioV2BringForwardButton" ) . click ( ) ;
1352+ await expect ( page . locator ( "#objectVectorStudioV2JsonDetails" ) ) . toContainText ( '"order": 2' ) ;
1353+ await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / O K S h a p e r e c t a n g l e - 1 z - o r d e r f o r w a r d \. / ) ;
1354+ await page . locator ( "#objectVectorStudioV2SendToBackButton" ) . click ( ) ;
1355+ await expect ( page . locator ( "#objectVectorStudioV2JsonDetails" ) ) . toContainText ( '"order": 1' ) ;
1356+ await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / O K S h a p e r e c t a n g l e - 1 z - o r d e r b a c k \. / ) ;
1357+
1358+ await page . locator ( "#objectVectorStudioV2DuplicateShapeButton" ) . click ( ) ;
1359+ await expect ( page . locator ( "#objectVectorStudioV2ShapeCount" ) ) . toHaveValue ( "3 shapes" ) ;
1360+ await expect ( page . locator ( "#objectVectorStudioV2RenderSurface [data-shape-id='rectangle-3']" ) ) . toHaveClass ( / i s - s e l e c t e d / ) ;
1361+ await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / O K D u p l i c a t e d s h a p e r e c t a n g l e - 1 a s r e c t a n g l e - 3 \. / ) ;
1362+ await page . locator ( "#objectVectorStudioV2RenderSurface" ) . focus ( ) ;
1363+ await page . keyboard . press ( "Delete" ) ;
1364+ await expect ( page . locator ( "#objectVectorStudioV2ShapeCount" ) ) . toHaveValue ( "2 shapes" ) ;
1365+ await expect ( page . locator ( "#objectVectorStudioV2RenderSurface [data-shape-id='rectangle-3']" ) ) . toHaveCount ( 0 ) ;
1366+ await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / O K D e l e t e d s h a p e r e c t a n g l e - 3 f r o m k e y b o a r d \. / ) ;
1367+
1368+ await page . locator ( "#objectVectorStudioV2ZoomInButton" ) . click ( ) ;
1369+ await expect ( page . locator ( "#objectVectorStudioV2CoordinateDisplay" ) ) . toContainText ( "Zoom 125%" ) ;
1370+ await expect ( page . locator ( "#objectVectorStudioV2RenderSurface" ) ) . toHaveAttribute ( "viewBox" , "0 0 256 176" ) ;
1371+ await page . locator ( "#objectVectorStudioV2PanRightButton" ) . click ( ) ;
1372+ await expect ( page . locator ( "#objectVectorStudioV2RenderSurface" ) ) . toHaveAttribute ( "viewBox" , "20 0 256 176" ) ;
1373+ await page . locator ( "#objectVectorStudioV2ResetViewButton" ) . click ( ) ;
1374+ await expect ( page . locator ( "#objectVectorStudioV2RenderSurface" ) ) . toHaveAttribute ( "viewBox" , "0 0 320 220" ) ;
1375+ await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / O K V i e w p o r t r e s e t t o 1 0 0 % a t o r i g i n \. / ) ;
13081376
13091377 await page . locator ( '[data-object-id="object-2"]' ) . click ( ) ;
13101378 await expect ( page . locator ( '[data-object-id="object-2"]' ) ) . toHaveAttribute ( "aria-pressed" , "true" ) ;
@@ -1318,6 +1386,14 @@ test.describe("Workspace Manager V2 bootstrap", () => {
13181386 await expect ( page . locator ( "#objectVectorStudioV2JsonDetails" ) ) . toContainText ( '"name": "Object 2 Renamed"' ) ;
13191387 await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / O K R e n a m e d o b j e c t o b j e c t - 2 t o O b j e c t 2 R e n a m e d \. / ) ;
13201388
1389+ await page . locator ( "#objectVectorStudioV2DuplicateObjectButton" ) . click ( ) ;
1390+ await expect ( page . locator ( "#objectVectorStudioV2ObjectCount" ) ) . toHaveValue ( "19 objects" ) ;
1391+ await expect ( page . locator ( '[data-object-id="object-2-renamed-copy"]' ) ) . toHaveAttribute ( "aria-pressed" , "true" ) ;
1392+ await expect ( page . locator ( "#statusLog" ) ) . toHaveValue ( / O K D u p l i c a t e d o b j e c t O b j e c t 2 R e n a m e d a s O b j e c t 2 R e n a m e d C o p y \. / ) ;
1393+ await page . locator ( "#objectVectorStudioV2DeleteObjectButton" ) . click ( ) ;
1394+ await expect ( page . locator ( "#objectVectorStudioV2ObjectCount" ) ) . toHaveValue ( "18 objects" ) ;
1395+ await expect ( page . locator ( '[data-object-id="object-2-renamed-copy"]' ) ) . toHaveCount ( 0 ) ;
1396+
13211397 await page . locator ( "#objectVectorStudioV2ObjectNameInput" ) . fill ( "Shield Pickup" ) ;
13221398 await page . locator ( "#objectVectorStudioV2AddObjectButton" ) . click ( ) ;
13231399 await expect ( page . locator ( "#objectVectorStudioV2ObjectCount" ) ) . toHaveValue ( "19 objects" ) ;
0 commit comments