import assert from "node:assert/strict"; import fs from "node:fs"; import vm from "node:vm"; const sourcePath = new URL("../web/js/o1keyReferenceImageEditor.js", import.meta.url); const source = fs.readFileSync(sourcePath, "utf8"); const executableSource = source.replace(/^export /gm, ""); const context = vm.createContext({ console }); vm.runInContext(executableSource, context, { filename: sourcePath.pathname }); const fitCropToRatio = vm.runInContext("fitCropToRatio", context); const constrainCropRect = vm.runInContext("constrainCropRect", context); const editedReferenceFilename = vm.runInContext("editedReferenceFilename", context); const fitStickerTransform = vm.runInContext("fitStickerTransform", context); const stickerControlGeometry = vm.runInContext("stickerControlGeometry", context); const hitTestSticker = vm.runInContext("hitTestSticker", context); const arrowHeadGeometry = vm.runInContext("arrowHeadGeometry", context); const ratios = vm.runInContext("REFERENCE_EDITOR_RATIOS", context); assert.deepEqual( JSON.parse(JSON.stringify(fitCropToRatio(1600, 900, 1))), { x: 350, y: 0, width: 900, height: 900 }, ); assert.deepEqual( JSON.parse(JSON.stringify(fitStickerTransform(1000, 500, 800, 600))), { x: 400, y: 300, width: 400, height: 200, rotation: 0, opacity: 1 }, ); const rotatedSticker = { x: 100, y: 100, width: 40, height: 20, rotation: Math.PI / 2 }; const rotatedGeometry = JSON.parse(JSON.stringify(stickerControlGeometry(rotatedSticker, 30))); assert.ok(Math.abs(rotatedGeometry.corners[0].x - 110) < 1e-9); assert.ok(Math.abs(rotatedGeometry.corners[0].y - 80) < 1e-9); assert.equal(hitTestSticker({ ...rotatedSticker, rotation: 0 }, { x: 100, y: 100 }), "move"); assert.equal(hitTestSticker({ ...rotatedSticker, rotation: 0 }, { x: 80, y: 90 }), "scale"); assert.equal(hitTestSticker({ ...rotatedSticker, rotation: 0 }, { x: 100, y: 60 }, 8, 30), "rotate"); assert.equal(hitTestSticker({ ...rotatedSticker, rotation: 0 }, { x: 10, y: 10 }), null); const arrowHead = JSON.parse(JSON.stringify(arrowHeadGeometry({ x: 0, y: 0 }, { x: 100, y: 0 }, 4))); assert.deepEqual(arrowHead.tip, { x: 100, y: 0 }); assert.ok(Math.abs(arrowHead.left.x - arrowHead.right.x) < 1e-9); assert.ok(Math.abs(arrowHead.left.y + arrowHead.right.y) < 1e-9); assert.ok(arrowHead.left.x < arrowHead.tip.x); assert.deepEqual( JSON.parse(JSON.stringify(fitCropToRatio(1600, 900, 4 / 3))), { x: 200, y: 0, width: 1200, height: 900 }, ); assert.deepEqual( JSON.parse(JSON.stringify(fitCropToRatio(600, 900, "original"))), { x: 0, y: 0, width: 600, height: 900 }, ); assert.deepEqual( JSON.parse(JSON.stringify(constrainCropRect({ x: -20, y: 880, width: 300, height: 100 }, 1000, 900))), { x: 0, y: 800, width: 300, height: 100 }, ); assert.deepEqual( JSON.parse(JSON.stringify(constrainCropRect({ x: 950, y: 850, width: 5000, height: 5000 }, 1000, 900))), { x: 0, y: 0, width: 1000, height: 900 }, ); assert.equal(editedReferenceFilename("products/look.v2.jpg"), "look.v2_edited.png"); assert.equal(editedReferenceFilename("bad:name?.webp"), "bad_name__edited.png"); assert.deepEqual( JSON.parse(JSON.stringify(ratios.map((item) => item.key))), ["free", "original", "1:1", "4:3", "3:4", "3:2", "2:3", "16:9", "9:16"], ); assert.match(source, /\["crop", "裁剪"/); assert.match(source, /\["mask", "遮罩"/); assert.match(source, /\["brush", "画笔"/); assert.match(source, /\["sticker", "贴图"/); assert.match(source, /\["arrow", "箭头"/); assert.match(source, /不会创建 MASK 数据/); assert.match(source, /#\$\{EDITOR_ID\} \[hidden\]\{display:none!important;\}/); assert.match(source, /overflow-x:hidden;overflow-y:auto/); assert.match(source, /historyRow\.append\(undo, redo\)/); assert.match(source, /sidebarActions\.append\(historyRow, clearMarks, reset\)/); assert.match(source, /clearMarks\.hidden = state\.mode !== "mask" && state\.mode !== "brush" && state\.mode !== "arrow"/); assert.match(source, /state\.mode === "sticker" \? "重置贴图"/); assert.match(source, /white-space:nowrap/); assert.match(source, /cursor:not-allowed/); assert.doesNotMatch(source, /cursor:wait/); assert.match(source, /outputContext\.drawImage\(/); assert.match(source, /URL\.createObjectURL\(file\)/); assert.match(source, /URL\.revokeObjectURL\(objectUrl\)/); assert.match(source, /drawSticker\(outputContext, state\.sticker/); assert.match(source, /state\.activeStroke\.tool === "arrow"/); assert.match(source, /松开位置就是箭头尖端/); assert.match(source, /await onConfirm\(\{/); assert.match(source, /canvas\.toBlob/); assert.doesNotMatch(source, /api\.fetchApi|authorization|base64/iu); console.log("o1key reference image editor tests passed");