@@ -2023,7 +2023,7 @@ test.describe("Workspace Manager V2 bootstrap", () => {
20232023 opacityLabels: Array.from(opacityRow.querySelectorAll("label > span")).map((label) => label.textContent.trim()),
20242024 opacityOrder: Array.from(opacityRow.children).map((element) => element.textContent.trim().replace(/\s+/g, " ")),
20252025 pickerIconOnly: content.querySelector("#objectVectorStudioV2PalettePickerButton").textContent.trim() === "",
2026- pickerRightOfStrokeControls : pickerButton.left >= strokeButton .right && pickerButton.left >= widthLabel.right ,
2026+ pickerBetweenPaintAndStroke : pickerButton.left >= paintButton .right && pickerButton.right <= strokeButton.left ,
20272027 primaryInline: [strokeButton, widthLabel, pickerButton].every((rect) => Math.abs((paintButton.top + paintButton.height / 2) - (rect.top + rect.height / 2)) < 4),
20282028 primaryOrder: Array.from(primaryRow.children).map((element) => element.matches("label") ? element.querySelector("span").textContent.trim() : (element.getAttribute("aria-label") || element.textContent).trim()),
20292029 widthInputFitsXxDotX: Math.round(widthInput.width) >= 58,
@@ -2042,9 +2042,9 @@ test.describe("Workspace Manager V2 bootstrap", () => {
20422042 opacityLabels: ["Fill", "Stroke"],
20432043 opacityOrder: ["Opacity", "Fill", "Stroke"],
20442044 pickerIconOnly: true,
2045- pickerRightOfStrokeControls : true,
2045+ pickerBetweenPaintAndStroke : true,
20462046 primaryInline: true,
2047- primaryOrder: ["Paint", "Stroke ", "Width ", "Picker "],
2047+ primaryOrder: ["Paint", "Picker ", "Stroke ", "Width "],
20482048 widthInputFitsXxDotX: true,
20492049 widthIsRightOfStroke: true
20502050 });
@@ -3829,6 +3829,78 @@ test.describe("Workspace Manager V2 bootstrap", () => {
38293829 await drawObjectVectorShape(page, "line", [{ x: 5.25, y: 6.5 }, { x: 7.75, y: 8.25 }]);
38303830 const unsnappedLine = await page.evaluate(() => window.__objectVectorStudioV2App.selectedShape().geometry);
38313831 expect(unsnappedLine).toEqual({ point1: { x: 5.25, y: 6.5 }, point2: { x: 7.75, y: 8.25 } });
3832+ await drawObjectVectorShape(page, "line", [{ x: 5.1234, y: 6.5678 }, { x: 7.9876, y: 8.5432 }]);
3833+ const snapNoneFormattedLine = await page.evaluate(() => {
3834+ const geometry = window.__objectVectorStudioV2App.selectedShape().geometry;
3835+ const decimalLength = (value) => {
3836+ const [, decimals = ""] = String(value).split(".");
3837+ return decimals.length;
3838+ };
3839+ return {
3840+ geometry,
3841+ maxDecimals: Math.max(
3842+ decimalLength(geometry.point1.x),
3843+ decimalLength(geometry.point1.y),
3844+ decimalLength(geometry.point2.x),
3845+ decimalLength(geometry.point2.y)
3846+ )
3847+ };
3848+ });
3849+ expect(snapNoneFormattedLine.geometry.point1.x).toBeCloseTo(5.123, 3);
3850+ expect(snapNoneFormattedLine.geometry.point1.y).toBeCloseTo(6.568, 3);
3851+ expect(snapNoneFormattedLine.geometry.point2.x).toBeCloseTo(7.988, 3);
3852+ expect(snapNoneFormattedLine.geometry.point2.y).toBeCloseTo(8.543, 3);
3853+ expect(snapNoneFormattedLine.maxDecimals).toBeLessThanOrEqual(3);
3854+
3855+ await page.locator("#objectVectorStudioV2AngleSnapButton").click();
3856+ await expect(page.locator("#objectVectorStudioV2AngleSnapButton")).toHaveAttribute("aria-pressed", "true");
3857+ await page.locator("#objectVectorStudioV2SnapAngleStepSelect").selectOption("45");
3858+ await drawObjectVectorShape(page, "line", [{ x: 0, y: 0 }, { x: 10, y: 3 }]);
3859+ await drawObjectVectorShape(page, "polyline", [{ x: 20, y: 0 }, { x: 30, y: 3 }, { x: 38, y: 10 }]);
3860+ await drawObjectVectorShape(page, "polygon", [{ x: -30, y: 0 }, { x: -20, y: 3 }, { x: -12, y: 11 }, { x: -30, y: 14 }]);
3861+ const angleSnappedDrawing = await page.evaluate(() => {
3862+ const app = window.__objectVectorStudioV2App;
3863+ const shapeByTool = (tool) => [...app.selectedObject().shapes].reverse().find((shape) => shape.tool === tool);
3864+ const pointsForShape = (shape) => shape.tool === "line" ? [shape.geometry.point1, shape.geometry.point2] : shape.geometry.points;
3865+ const decimalLength = (value) => {
3866+ const [, decimals = ""] = String(value).split(".");
3867+ return decimals.length;
3868+ };
3869+ const segmentSnapsToStep = (start, end, step) => {
3870+ const dx = end.x - start.x;
3871+ const dy = end.y - start.y;
3872+ const degrees = ((Math.atan2(dy, dx) * 180 / Math.PI) % 360 + 360) % 360;
3873+ const nearest = Math.round(degrees / step) * step;
3874+ const wrappedDelta = Math.abs(((degrees - nearest + 540) % 360) - 180);
3875+ return wrappedDelta < 0.05;
3876+ };
3877+ const collect = (tool) => {
3878+ const shape = shapeByTool(tool);
3879+ const points = pointsForShape(shape);
3880+ const coordinates = points.flatMap((point) => [point.x, point.y]);
3881+ return {
3882+ geometry: shape.geometry,
3883+ maxDecimals: Math.max(...coordinates.map(decimalLength)),
3884+ segmentAnglesSnapped: points.slice(1).map((point, index) => segmentSnapsToStep(points[index], point, 45))
3885+ };
3886+ };
3887+ return {
3888+ angleStep: app.angleSnapStep,
3889+ line: collect("line"),
3890+ polygon: collect("polygon"),
3891+ polyline: collect("polyline")
3892+ };
3893+ });
3894+ expect(angleSnappedDrawing.angleStep).toBe(45);
3895+ expect(angleSnappedDrawing.line.segmentAnglesSnapped).toEqual([true]);
3896+ expect(angleSnappedDrawing.polyline.segmentAnglesSnapped).toEqual([true, true]);
3897+ expect(angleSnappedDrawing.polygon.segmentAnglesSnapped).toEqual([true, true, true]);
3898+ expect(angleSnappedDrawing.line.maxDecimals).toBeLessThanOrEqual(3);
3899+ expect(angleSnappedDrawing.polyline.maxDecimals).toBeLessThanOrEqual(3);
3900+ expect(angleSnappedDrawing.polygon.maxDecimals).toBeLessThanOrEqual(3);
3901+ await page.locator("#objectVectorStudioV2AngleSnapButton").click();
3902+ await expect(page.locator("#objectVectorStudioV2AngleSnapButton")).toHaveAttribute("aria-pressed", "false");
3903+
38323904 await page.locator("#objectVectorStudioV2SnapModeButton").click();
38333905 await expect(page.locator("#objectVectorStudioV2SnapModeButton")).toHaveText("Snap Grid");
38343906 await expect(page.locator("#objectVectorStudioV2SnapModeButton")).toHaveAttribute("data-snap-mode", "grid");
0 commit comments