From 25c1fdd22d30437f9879f47fa0817701fb6d625d Mon Sep 17 00:00:00 2001 From: ienaga Date: Tue, 1 Apr 2025 16:21:55 +0900 Subject: [PATCH 01/13] #175 add UnitTest(@next2d/renderer) --- .../TextFieldGenerateFontStyleService.test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 packages/renderer/src/TextField/service/TextFieldGenerateFontStyleService.test.ts diff --git a/packages/renderer/src/TextField/service/TextFieldGenerateFontStyleService.test.ts b/packages/renderer/src/TextField/service/TextFieldGenerateFontStyleService.test.ts new file mode 100644 index 00000000..43ef50a3 --- /dev/null +++ b/packages/renderer/src/TextField/service/TextFieldGenerateFontStyleService.test.ts @@ -0,0 +1,17 @@ +import { execute } from "./TextFieldGenerateFontStyleService"; +import { describe, expect, it } from "vitest"; +import type { ITextFormat } from "../../interface/ITextFormat"; + +describe("TextFieldGenerateFontStyleService.js test", () => +{ + it("execute test", () => + { + const mockTextFormat = { + italic: true, + bold: true, + size: 12, + font: "Arial", + } as ITextFormat; + expect(execute(mockTextFormat)).toBe("italic bold 12px 'Arial','sans-serif'"); + }); +}); \ No newline at end of file From 2ebaa7d0ad828b25cc8123a9d6d26445c68f8735 Mon Sep 17 00:00:00 2001 From: ienaga Date: Tue, 1 Apr 2025 17:59:53 +0900 Subject: [PATCH 02/13] #175 add UnitTest(@next2d/webgl)(WIP) --- package.json | 2 +- ...ferObjectMeguruBinarySearchService.test.ts | 6 +- ...orBufferObjectAcquireObjectUseCase.test.ts | 4 + ...rObjectGetColorBufferObjectUseCase.test.ts | 4 + ...ectReleaseColorBufferObjectUseCase.test.ts | 7 +- ...nagerUnBindAttachmentObjectService.test.ts | 9 +- .../Mask/service/MaskBeginMaskService.test.ts | 115 ++++++++++++ .../Mask/service/MaskEndMaskService.test.ts | 105 +++++++++++ .../service/MaskSetMaskBoundsService.test.ts | 81 ++++++++ .../Mask/service/MaskUnionMaskService.test.ts | 176 ++++++++++++++++++ 10 files changed, 503 insertions(+), 6 deletions(-) create mode 100644 packages/webgl/src/Mask/service/MaskBeginMaskService.test.ts create mode 100644 packages/webgl/src/Mask/service/MaskEndMaskService.test.ts create mode 100644 packages/webgl/src/Mask/service/MaskSetMaskBoundsService.test.ts create mode 100644 packages/webgl/src/Mask/service/MaskUnionMaskService.test.ts diff --git a/package.json b/package.json index aef47d60..a4bf73e2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@next2d/player", - "version": "2.1.2", + "version": "2.1.3", "description": "Experience the fast and beautiful anti-aliased rendering of WebGL. You can create rich, interactive graphics, cross-platform applications and games without worrying about browser or device compatibility.", "author": "Toshiyuki Ienaga (https://github.com/ienaga/)", "license": "MIT", diff --git a/packages/webgl/src/ColorBufferObject/service/ColorBufferObjectMeguruBinarySearchService.test.ts b/packages/webgl/src/ColorBufferObject/service/ColorBufferObjectMeguruBinarySearchService.test.ts index 0c6ee25d..25110ba4 100644 --- a/packages/webgl/src/ColorBufferObject/service/ColorBufferObjectMeguruBinarySearchService.test.ts +++ b/packages/webgl/src/ColorBufferObject/service/ColorBufferObjectMeguruBinarySearchService.test.ts @@ -1,5 +1,5 @@ import { execute } from "./ColorBufferObjectMeguruBinarySearchService"; -import { describe, expect, it, vi } from "vitest"; +import { describe, expect, it } from "vitest"; import { $objectPool } from "../../ColorBufferObject"; describe("ColorBufferObjectMeguruBinarySearchService.js method test", () => @@ -11,6 +11,7 @@ describe("ColorBufferObjectMeguruBinarySearchService.js method test", () => { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 0, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -25,6 +26,7 @@ describe("ColorBufferObjectMeguruBinarySearchService.js method test", () => { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 1, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -39,6 +41,7 @@ describe("ColorBufferObjectMeguruBinarySearchService.js method test", () => { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 2, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -53,6 +56,7 @@ describe("ColorBufferObjectMeguruBinarySearchService.js method test", () => { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 3, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, diff --git a/packages/webgl/src/ColorBufferObject/usecase/ColorBufferObjectAcquireObjectUseCase.test.ts b/packages/webgl/src/ColorBufferObject/usecase/ColorBufferObjectAcquireObjectUseCase.test.ts index 22c606ad..990dc82c 100644 --- a/packages/webgl/src/ColorBufferObject/usecase/ColorBufferObjectAcquireObjectUseCase.test.ts +++ b/packages/webgl/src/ColorBufferObject/usecase/ColorBufferObjectAcquireObjectUseCase.test.ts @@ -28,6 +28,7 @@ describe("ColorBufferObjectAcquireObjectUseCase.js method test", () => { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 0, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -42,6 +43,7 @@ describe("ColorBufferObjectAcquireObjectUseCase.js method test", () => { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 1, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -56,6 +58,7 @@ describe("ColorBufferObjectAcquireObjectUseCase.js method test", () => { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 2, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -70,6 +73,7 @@ describe("ColorBufferObjectAcquireObjectUseCase.js method test", () => { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 3, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, diff --git a/packages/webgl/src/ColorBufferObject/usecase/ColorBufferObjectGetColorBufferObjectUseCase.test.ts b/packages/webgl/src/ColorBufferObject/usecase/ColorBufferObjectGetColorBufferObjectUseCase.test.ts index 71a5d054..12ef1221 100644 --- a/packages/webgl/src/ColorBufferObject/usecase/ColorBufferObjectGetColorBufferObjectUseCase.test.ts +++ b/packages/webgl/src/ColorBufferObject/usecase/ColorBufferObjectGetColorBufferObjectUseCase.test.ts @@ -24,6 +24,7 @@ describe("ColorBufferObjectGetColorBufferObjectUseCase.js method test", () => { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 0, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -38,6 +39,7 @@ describe("ColorBufferObjectGetColorBufferObjectUseCase.js method test", () => { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 1, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -52,6 +54,7 @@ describe("ColorBufferObjectGetColorBufferObjectUseCase.js method test", () => { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 2, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -66,6 +69,7 @@ describe("ColorBufferObjectGetColorBufferObjectUseCase.js method test", () => { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 3, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, diff --git a/packages/webgl/src/ColorBufferObject/usecase/ColorBufferObjectReleaseColorBufferObjectUseCase.test.ts b/packages/webgl/src/ColorBufferObject/usecase/ColorBufferObjectReleaseColorBufferObjectUseCase.test.ts index 9d24e6f4..5741bd85 100644 --- a/packages/webgl/src/ColorBufferObject/usecase/ColorBufferObjectReleaseColorBufferObjectUseCase.test.ts +++ b/packages/webgl/src/ColorBufferObject/usecase/ColorBufferObjectReleaseColorBufferObjectUseCase.test.ts @@ -1,6 +1,7 @@ import { execute } from "./ColorBufferObjectReleaseColorBufferObjectUseCase"; import { describe, expect, it } from "vitest"; import { $objectPool } from "../../ColorBufferObject"; +import type { IColorBufferObject } from "../../interface/IColorBufferObject"; describe("ColorBufferObjectReleaseColorBufferObjectUseCase.js method test", () => { @@ -11,6 +12,7 @@ describe("ColorBufferObjectReleaseColorBufferObjectUseCase.js method test", () = { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 0, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -25,6 +27,7 @@ describe("ColorBufferObjectReleaseColorBufferObjectUseCase.js method test", () = { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 1, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -39,6 +42,7 @@ describe("ColorBufferObjectReleaseColorBufferObjectUseCase.js method test", () = { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 2, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -53,6 +57,7 @@ describe("ColorBufferObjectReleaseColorBufferObjectUseCase.js method test", () = { "resource": {} as unknown as WebGLRenderbuffer, "stencil": { + "id": 3, "resource": {} as unknown as WebGLRenderbuffer, "width": 0, "height": 0, @@ -80,7 +85,7 @@ describe("ColorBufferObjectReleaseColorBufferObjectUseCase.js method test", () = "height": 480, "area": 620 * 480, "dirty": false, - }; + } as IColorBufferObject; execute(colorBufferObject); expect($objectPool.length).toBe(5); expect($objectPool[2]).toBe(colorBufferObject); diff --git a/packages/webgl/src/FrameBufferManager/service/FrameBufferManagerUnBindAttachmentObjectService.test.ts b/packages/webgl/src/FrameBufferManager/service/FrameBufferManagerUnBindAttachmentObjectService.test.ts index 79468133..e46b2206 100644 --- a/packages/webgl/src/FrameBufferManager/service/FrameBufferManagerUnBindAttachmentObjectService.test.ts +++ b/packages/webgl/src/FrameBufferManager/service/FrameBufferManagerUnBindAttachmentObjectService.test.ts @@ -23,7 +23,7 @@ describe("FrameBufferManagerUnBindAttachmentObjectService.js method test", () => } }); - const attachmentObject: IAttachmentObject = { + const attachmentObject = { "width": 100, "height": 100, "clipLevel": 0, @@ -31,21 +31,24 @@ describe("FrameBufferManagerUnBindAttachmentObjectService.js method test", () => "mask": false, "color": null, "texture": { + "id": 0, "resource": "createTexture", "width": 100, "height": 100, "area": 100 * 100, + "smooth": false }, "stencil": { + "id": 0, "resource": "createRenderbuffer", "width": 100, "height": 100, "area": 100 * 100, "dirty": false, } - } + } as unknown as IAttachmentObject; - $setCurrentAttachment(attachmentObject) + $setCurrentAttachment(attachmentObject); expect($getCurrentAttachment()).toBe(attachmentObject); $setFramebufferBound(true); diff --git a/packages/webgl/src/Mask/service/MaskBeginMaskService.test.ts b/packages/webgl/src/Mask/service/MaskBeginMaskService.test.ts new file mode 100644 index 00000000..10fc573c --- /dev/null +++ b/packages/webgl/src/Mask/service/MaskBeginMaskService.test.ts @@ -0,0 +1,115 @@ +import { execute } from "./MaskBeginMaskService"; +import { describe, expect, it, vi } from "vitest"; +import type { IAttachmentObject } from "../../interface/IAttachmentObject.ts"; +import { + $setCurrentAttachment, + $getCurrentAttachment +} from "../../FrameBufferManager.ts"; +import { + $isMaskDrawing, + $setMaskDrawing, + $clipLevels +} from "../../Mask"; + +describe("MaskBeginMaskService.js method test", () => +{ + it("test case", () => + { + vi.mock("../../WebGLUtil.ts", async (importOriginal) => + { + const mod = await importOriginal(); + return { + ...mod, + $gl: { + "createTexture": vi.fn(() => { return "createTexture" }), + "activeTexture": vi.fn(() => { return "activeTexture" }), + "bindTexture": vi.fn(() => { return "bindTexture" }), + "texParameteri": vi.fn(() => { return "texParameteri" }), + "texStorage2D": vi.fn(() => { return "texStorage2D" }), + "createRenderbuffer": vi.fn(() => { return "createRenderbuffer" }), + "bindRenderbuffer": vi.fn(() => { return "bindRenderbuffer" }), + "renderbufferStorage": vi.fn(() => { return "renderbufferStorage" }), + "enable": vi.fn((cap) => { + switch (cap) { + case "STENCIL_TEST": + case "SAMPLE_ALPHA_TO_COVERAGE": + return ; + + default: + throw new Error("Unknown capability: " + cap); + + } + }), + "stencilFunc": vi.fn((func, ref, mask) => { + expect(func).toBe("ALWAYS"); + expect(ref).toBe(0); + expect(mask).toBe(0xff); + }), + "stencilOp": vi.fn((fail, zfail, zpass) => + { + expect(fail).toBe("ZERO"); + expect(zfail).toBe("INVERT"); + expect(zpass).toBe("INVERT"); + }), + "colorMask": vi.fn((red, green, blue, alpha) => + { + expect(red).toBe(false); + expect(green).toBe(false); + expect(blue).toBe(false); + expect(alpha).toBe(false); + }), + "STENCIL_TEST": "STENCIL_TEST", + "SAMPLE_ALPHA_TO_COVERAGE": "SAMPLE_ALPHA_TO_COVERAGE", + "ALWAYS": "ALWAYS", + "ZERO": "ZERO", + "INVERT": "INVERT", + }, + "$context": { + get currentAttachmentObject() { + return $getCurrentAttachment(); + } + } + } + }); + + const attachmentObject = { + "width": 100, + "height": 100, + "clipLevel": 0, + "msaa": false, + "mask": false, + "color": null, + "texture": { + "id": 0, + "resource": "createTexture", + "width": 100, + "height": 100, + "area": 100 * 100, + "smooth": false + }, + "stencil": { + "id": 0, + "resource": "createRenderbuffer", + "width": 100, + "height": 100, + "area": 100 * 100, + "dirty": false, + } + } as unknown as IAttachmentObject; + + $setCurrentAttachment(attachmentObject); + + $setMaskDrawing(false); + expect($isMaskDrawing()).toBe(false); + + $clipLevels.clear(); + expect($clipLevels.size).toBe(0); + + execute(); + + expect($clipLevels.size).toBe(1); + expect($isMaskDrawing()).toBe(true); + expect(attachmentObject.mask).toBe(true); + expect(attachmentObject.clipLevel).toBe(1); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mask/service/MaskEndMaskService.test.ts b/packages/webgl/src/Mask/service/MaskEndMaskService.test.ts new file mode 100644 index 00000000..0fb0cb59 --- /dev/null +++ b/packages/webgl/src/Mask/service/MaskEndMaskService.test.ts @@ -0,0 +1,105 @@ +import { execute } from "./MaskEndMaskService"; +import { describe, expect, it, vi } from "vitest"; +import type { IAttachmentObject } from "../../interface/IAttachmentObject.ts"; +import { + $setCurrentAttachment, + $getCurrentAttachment +} from "../../FrameBufferManager.ts"; + +describe("MaskEndMaskService.js method test", () => +{ + it("test case", () => + { + vi.mock("../../WebGLUtil.ts", async (importOriginal) => + { + const mod = await importOriginal(); + return { + ...mod, + $gl: { + "createTexture": vi.fn(() => { return "createTexture" }), + "activeTexture": vi.fn(() => { return "activeTexture" }), + "bindTexture": vi.fn(() => { return "bindTexture" }), + "texParameteri": vi.fn(() => { return "texParameteri" }), + "texStorage2D": vi.fn(() => { return "texStorage2D" }), + "createRenderbuffer": vi.fn(() => { return "createRenderbuffer" }), + "bindRenderbuffer": vi.fn(() => { return "bindRenderbuffer" }), + "renderbufferStorage": vi.fn(() => { return "renderbufferStorage" }), + "disable": vi.fn((cap) => { + switch (cap) { + case "SCISSOR_TEST": + case "SAMPLE_ALPHA_TO_COVERAGE": + return ; + + default: + throw new Error("Unknown capability: " + cap); + + } + }), + "stencilFunc": vi.fn((func, ref, mask) => { + expect(func).toBe("EQUAL"); + expect(ref).toBe(1); + expect(mask).toBe(1); + }), + "stencilOp": vi.fn((fail, zfail, zpass) => + { + expect(fail).toBe("KEEP"); + expect(zfail).toBe("KEEP"); + expect(zpass).toBe("KEEP"); + }), + "colorMask": vi.fn((red, green, blue, alpha) => + { + expect(red).toBe(true); + expect(green).toBe(true); + expect(blue).toBe(true); + expect(alpha).toBe(true); + }), + "stencilMask": vi.fn((mask) => + { + expect(mask).toBe(0xff); + }), + "STENCIL_TEST": "STENCIL_TEST", + "SAMPLE_ALPHA_TO_COVERAGE": "SAMPLE_ALPHA_TO_COVERAGE", + "ALWAYS": "ALWAYS", + "ZERO": "ZERO", + "INVERT": "INVERT", + "EQUAL": "EQUAL", + "KEEP": "KEEP", + "SCISSOR_TEST": "SCISSOR_TEST", + }, + "$context": { + get currentAttachmentObject() { + return $getCurrentAttachment(); + } + } + } + }); + + const attachmentObject = { + "width": 100, + "height": 100, + "clipLevel": 1, + "msaa": false, + "mask": false, + "color": null, + "texture": { + "id": 0, + "resource": "createTexture", + "width": 100, + "height": 100, + "area": 100 * 100, + "smooth": false + }, + "stencil": { + "id": 0, + "resource": "createRenderbuffer", + "width": 100, + "height": 100, + "area": 100 * 100, + "dirty": false, + } + } as unknown as IAttachmentObject; + + $setCurrentAttachment(attachmentObject); + execute(); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mask/service/MaskSetMaskBoundsService.test.ts b/packages/webgl/src/Mask/service/MaskSetMaskBoundsService.test.ts new file mode 100644 index 00000000..84afdaa8 --- /dev/null +++ b/packages/webgl/src/Mask/service/MaskSetMaskBoundsService.test.ts @@ -0,0 +1,81 @@ +import { execute } from "./MaskSetMaskBoundsService"; +import { describe, expect, it, vi } from "vitest"; +import type { IAttachmentObject } from "../../interface/IAttachmentObject.ts"; +import { + $setCurrentAttachment, + $getCurrentAttachment +} from "../../FrameBufferManager.ts"; +import { $clipBounds } from "../../Mask"; + +describe("MaskSetMaskBoundsService.js method test", () => +{ + it("test case", () => + { + vi.mock("../../WebGLUtil.ts", async (importOriginal) => + { + const mod = await importOriginal(); + return { + ...mod, + $gl: { + "createTexture": vi.fn(() => { return "createTexture" }), + "activeTexture": vi.fn(() => { return "activeTexture" }), + "bindTexture": vi.fn(() => { return "bindTexture" }), + "texParameteri": vi.fn(() => { return "texParameteri" }), + "texStorage2D": vi.fn(() => { return "texStorage2D" }), + "createRenderbuffer": vi.fn(() => { return "createRenderbuffer" }), + "bindRenderbuffer": vi.fn(() => { return "bindRenderbuffer" }), + "renderbufferStorage": vi.fn(() => { return "renderbufferStorage" }), + "enable": vi.fn((cap) => { + expect(cap).toBe("SCISSOR_TEST"); + }), + "scissor": vi.fn((x, y, width, height) => + { + expect(x).toBe(10); + expect(y).toBe(60); + expect(width).toBe(20); + expect(height).toBe(20); + }), + "SCISSOR_TEST": "SCISSOR_TEST", + }, + "$context": { + get currentAttachmentObject() { + return $getCurrentAttachment(); + } + } + } + }); + + const attachmentObject = { + "width": 100, + "height": 100, + "clipLevel": 1, + "msaa": false, + "mask": false, + "color": null, + "texture": { + "id": 0, + "resource": "createTexture", + "width": 100, + "height": 100, + "area": 100 * 100, + "smooth": false + }, + "stencil": { + "id": 0, + "resource": "createRenderbuffer", + "width": 100, + "height": 100, + "area": 100 * 100, + "dirty": false, + } + } as unknown as IAttachmentObject; + + $setCurrentAttachment(attachmentObject); + + $clipBounds.clear(); + expect($clipBounds.size).toBe(0); + + execute(10, 20, 30, 40); + expect($clipBounds.size).toBe(1); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mask/service/MaskUnionMaskService.test.ts b/packages/webgl/src/Mask/service/MaskUnionMaskService.test.ts new file mode 100644 index 00000000..5433b806 --- /dev/null +++ b/packages/webgl/src/Mask/service/MaskUnionMaskService.test.ts @@ -0,0 +1,176 @@ +import { execute } from "./MaskUnionMaskService"; +import { describe, expect, it, vi } from "vitest"; +import type { IAttachmentObject } from "../../interface/IAttachmentObject.ts"; +import { + $setCurrentAttachment, + $getCurrentAttachment +} from "../../FrameBufferManager.ts"; + +describe("MaskUnionMaskService.js method test", () => +{ + it("test case", () => + { + vi.mock("../../WebGLUtil.ts", async (importOriginal) => + { + const mod = await importOriginal(); + return { + ...mod, + $gl: { + "createTexture": vi.fn(() => { return "createTexture" }), + "activeTexture": vi.fn(() => { return "activeTexture" }), + "bindTexture": vi.fn(() => { return "bindTexture" }), + "texParameteri": vi.fn(() => { return "texParameteri" }), + "texStorage2D": vi.fn(() => { return "texStorage2D" }), + "createRenderbuffer": vi.fn(() => { return "createRenderbuffer" }), + "bindRenderbuffer": vi.fn(() => { return "bindRenderbuffer" }), + "renderbufferStorage": vi.fn(() => { return "renderbufferStorage" }), + "createProgram": vi.fn(() => { return "createProgram" }), + "createShader": vi.fn(() => { return "createShader" }), + "shaderSource": vi.fn(() => { return "shaderSource" }), + "compileShader": vi.fn(() => { return "compileShader" }), + "attachShader": vi.fn(() => { return "attachShader" }), + "linkProgram": vi.fn(() => { return "linkProgram" }), + "detachShader": vi.fn(() => { return "detachShader" }), + "deleteShader": vi.fn(() => { return "deleteShader" }), + "createVertexArray": vi.fn(() => { return "createVertexArray" }), + "createBuffer": vi.fn(() => { return "createBuffer" }), + "enableVertexAttribArray": vi.fn(() => { return "enableVertexAttribArray" }), + "vertexAttribPointer": vi.fn(() => { return "vertexAttribPointer" }), + "bindVertexArray": vi.fn(() => { return "bindVertexArray" }), + "useProgram": vi.fn(() => { return "useProgram" }), + "bindBuffer": vi.fn(() => { return "bindBuffer" }), + "bufferData": vi.fn(() => { return "bufferData" }), + "drawArrays": vi.fn(() => { return "drawArrays" }), + "blendFunc": vi.fn(() => { return "blendFunc" }), + "getProgramParameter": vi.fn(() => { return 0 }), + "disable": vi.fn((cap) => { + switch (cap) { + case "SCISSOR_TEST": + case "SAMPLE_ALPHA_TO_COVERAGE": + return ; + + default: + throw new Error("Unknown capability: " + cap); + + } + }), + "stencilFunc": vi.fn((func, ref, mask) => { + switch (func) { + case "ALWAYS": + case "LEQUAL": + break; + + default: + throw new Error("Unknown function: " + func); + } + + switch (ref) { + case 0: + case 1: + break; + + default: + throw new Error("Unknown function: " + func); + } + + switch (mask) { + case 255: + break; + + default: + throw new Error("Unknown function: " + func); + } + }), + "stencilOp": vi.fn((fail, zfail, zpass) => + { + switch (fail) { + case "ZERO": + case "REPLACE": + break; + + default: + throw new Error("Unknown function: " + fail); + } + switch (zfail) { + case "REPLACE": + case "INVERT": + break; + + default: + throw new Error("Unknown function: " + zfail); + } + switch (zpass) { + case "REPLACE": + case "INVERT": + break; + + default: + throw new Error("Unknown function: " + zpass); + } + }), + "colorMask": vi.fn((red, green, blue, alpha) => + { + expect(red).toBe(true); + expect(green).toBe(true); + expect(blue).toBe(true); + expect(alpha).toBe(true); + }), + "stencilMask": vi.fn((mask) => + { + switch (mask) { + case -3: + case 2: + case 255: + break; + + default: + throw new Error("Unknown mask: " + mask); + } + + }), + "STENCIL_TEST": "STENCIL_TEST", + "SAMPLE_ALPHA_TO_COVERAGE": "SAMPLE_ALPHA_TO_COVERAGE", + "ALWAYS": "ALWAYS", + "ZERO": "ZERO", + "REPLACE": "REPLACE", + "INVERT": "INVERT", + "LEQUAL": "LEQUAL", + "SCISSOR_TEST": "SCISSOR_TEST" + }, + "$context": { + get currentAttachmentObject() { + return $getCurrentAttachment(); + } + } + } + }); + + const attachmentObject = { + "width": 100, + "height": 100, + "clipLevel": 1, + "msaa": false, + "mask": false, + "color": null, + "texture": { + "id": 0, + "resource": "createTexture", + "width": 100, + "height": 100, + "area": 100 * 100, + "smooth": false + }, + "stencil": { + "id": 0, + "resource": "createRenderbuffer", + "width": 100, + "height": 100, + "area": 100 * 100, + "dirty": false, + } + } as unknown as IAttachmentObject; + + $setCurrentAttachment(attachmentObject); + execute(); + }); +}); \ No newline at end of file From 6ea73181534c8e26be23e84d12a2d7fbcb4b43c8 Mon Sep 17 00:00:00 2001 From: ienaga Date: Wed, 2 Apr 2025 06:49:58 +0900 Subject: [PATCH 03/13] #175 add UnitTest(@next2d/webgl)(WIP) --- .../src/Mask/usecase/MaskBindUseCase.test.ts | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 packages/webgl/src/Mask/usecase/MaskBindUseCase.test.ts diff --git a/packages/webgl/src/Mask/usecase/MaskBindUseCase.test.ts b/packages/webgl/src/Mask/usecase/MaskBindUseCase.test.ts new file mode 100644 index 00000000..343bdac7 --- /dev/null +++ b/packages/webgl/src/Mask/usecase/MaskBindUseCase.test.ts @@ -0,0 +1,78 @@ +import { execute } from "./MaskBindUseCase"; +import { describe, expect, it, vi } from "vitest"; +import { + $isMaskDrawing, + $setMaskDrawing +} from "../../Mask"; + +describe("MaskBindUseCase.js method test", () => +{ + it("test case1", () => + { + vi.mock("../../WebGLUtil.ts", async (importOriginal) => + { + const mod = await importOriginal(); + return { + ...mod, + "$gl": { + "enable": vi.fn((cap) => + { + expect(cap).toBe("STENCIL_TEST"); + }), + "STENCIL_TEST": "STENCIL_TEST", + }, + "$context": { + get currentAttachmentObject() { + return null; + } + } + } + }); + + $setMaskDrawing(false); + expect($isMaskDrawing()).toBe(false); + + execute(true); + expect($isMaskDrawing()).toBe(true); + + }); + + it("test case2", () => + { + vi.mock("../../WebGLUtil.ts", async (importOriginal) => + { + const mod = await importOriginal(); + return { + ...mod, + "$gl": { + "disable": vi.fn((cap) => + { + console.log(cap); + switch (cap) { + case "STENCIL_TEST": + case "SCISSOR_TEST": + return; + default: + throw new Error("Invalid cap"); + } + }), + "enable": vi.fn(), + "STENCIL_TEST": "STENCIL_TEST", + "SCISSOR_TEST": "SCISSOR_TEST", + }, + "$context": { + get currentAttachmentObject() { + return null; + } + } + } + }); + + $setMaskDrawing(true); + expect($isMaskDrawing()).toBe(true); + + execute(false); + expect($isMaskDrawing()).toBe(false); + + }); +}); \ No newline at end of file From 3c7c1595122425341f2a73156ce772bdca2678a4 Mon Sep 17 00:00:00 2001 From: ienaga Date: Fri, 4 Apr 2025 21:16:22 +0900 Subject: [PATCH 04/13] #175 add UnitTest(@next2d/webgl)(WIP) --- .../Mask/usecase/MaskLeaveMaskUseCase.test.ts | 322 ++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 packages/webgl/src/Mask/usecase/MaskLeaveMaskUseCase.test.ts diff --git a/packages/webgl/src/Mask/usecase/MaskLeaveMaskUseCase.test.ts b/packages/webgl/src/Mask/usecase/MaskLeaveMaskUseCase.test.ts new file mode 100644 index 00000000..58dad1f7 --- /dev/null +++ b/packages/webgl/src/Mask/usecase/MaskLeaveMaskUseCase.test.ts @@ -0,0 +1,322 @@ +import { execute } from "./MaskLeaveMaskUseCase"; +import { describe, expect, it, vi } from "vitest"; +import type { IAttachmentObject } from "../../interface/IAttachmentObject.ts"; +import { + $setCurrentAttachment, + $getCurrentAttachment +} from "../../FrameBufferManager.ts"; +import { + $setMaskDrawing, + $clipBounds, + $clipLevels, + $isMaskDrawing +} from "../../Mask"; + +describe("MaskLeaveMaskUseCase.js method test", () => +{ + it("test case1", () => + { + vi.mock("../../WebGLUtil.ts", async (importOriginal) => + { + const mod = await importOriginal(); + return { + ...mod, + $gl: { + "createTexture": vi.fn(() => { return "createTexture" }), + "activeTexture": vi.fn(() => { return "activeTexture" }), + "bindTexture": vi.fn(() => { return "bindTexture" }), + "texParameteri": vi.fn(() => { return "texParameteri" }), + "texStorage2D": vi.fn(() => { return "texStorage2D" }), + "createRenderbuffer": vi.fn(() => { return "createRenderbuffer" }), + "bindRenderbuffer": vi.fn(() => { return "bindRenderbuffer" }), + "renderbufferStorage": vi.fn(() => { return "renderbufferStorage" }), + "createProgram": vi.fn(() => { return "createProgram" }), + "createShader": vi.fn(() => { return "createShader" }), + "shaderSource": vi.fn(() => { return "shaderSource" }), + "compileShader": vi.fn(() => { return "compileShader" }), + "attachShader": vi.fn(() => { return "attachShader" }), + "linkProgram": vi.fn(() => { return "linkProgram" }), + "detachShader": vi.fn(() => { return "detachShader" }), + "deleteShader": vi.fn(() => { return "deleteShader" }), + "createVertexArray": vi.fn(() => { return "createVertexArray" }), + "createBuffer": vi.fn(() => { return "createBuffer" }), + "enableVertexAttribArray": vi.fn(() => { return "enableVertexAttribArray" }), + "vertexAttribPointer": vi.fn(() => { return "vertexAttribPointer" }), + "bindVertexArray": vi.fn(() => { return "bindVertexArray" }), + "useProgram": vi.fn(() => { return "useProgram" }), + "bindBuffer": vi.fn(() => { return "bindBuffer" }), + "bufferData": vi.fn(() => { return "bufferData" }), + "drawArrays": vi.fn(() => { return "drawArrays" }), + "blendFunc": vi.fn(() => { return "blendFunc" }), + "getProgramParameter": vi.fn(() => { return 0 }), + "enable": vi.fn((cap) => + { + expect(cap).toBe("SCISSOR_TEST"); + }), + "disable": vi.fn((cap) => + { + switch (cap) { + case "STENCIL_TEST": + case "SCISSOR_TEST": + break; + default: + throw new Error("Invalid cap"); + } + }), + "stencilFunc": vi.fn((func, ref, mask) => + { + expect(func).toBe("ALWAYS"); + expect(ref).toBe(0); + expect(mask).toBe(0x4); + }), + "stencilOp": vi.fn((fail, zfail, zpass) => + { + expect(fail).toBe("REPLACE"); + expect(zfail).toBe("REPLACE"); + expect(zpass).toBe("REPLACE"); + }), + "colorMask": vi.fn((red, green, blue, alpha) => + { + }), + "stencilMask": vi.fn((mask) => + { + }), + "scissor": vi.fn((x, y, width, height) => + { + expect(x).toBe(10); + expect(y).toBe(60); + expect(width).toBe(20); + expect(height).toBe(20); + }), + "clear": vi.fn((mask) => + { + expect(mask).toBe("STENCIL_BUFFER_BIT"); + }), + "STENCIL_TEST": "STENCIL_TEST", + "SAMPLE_ALPHA_TO_COVERAGE": "SAMPLE_ALPHA_TO_COVERAGE", + "ALWAYS": "ALWAYS", + "ZERO": "ZERO", + "REPLACE": "REPLACE", + "INVERT": "INVERT", + "LEQUAL": "LEQUAL", + "SCISSOR_TEST": "SCISSOR_TEST", + "STENCIL_BUFFER_BIT": "STENCIL_BUFFER_BIT", + }, + "$context": { + get currentAttachmentObject() { + return $getCurrentAttachment(); + } + } + } + }); + + const attachmentObject = { + "width": 100, + "height": 100, + "clipLevel": 1, + "msaa": false, + "mask": true, + "color": null, + "texture": { + "id": 0, + "resource": "createTexture", + "width": 100, + "height": 100, + "area": 100 * 100, + "smooth": false + }, + "stencil": { + "id": 0, + "resource": "createRenderbuffer", + "width": 100, + "height": 100, + "area": 100 * 100, + "dirty": false, + } + } as unknown as IAttachmentObject; + $setCurrentAttachment(attachmentObject); + + $clipBounds.set(1, new Float32Array([10, 20, 30, 40])); + expect($clipBounds.size).toBe(1); + + $clipLevels.set(1, 1); + expect($clipLevels.size).toBe(1); + + $setMaskDrawing(true); + expect($isMaskDrawing()).toBe(true); + + execute(); + + expect($clipBounds.size).toBe(0); + expect($clipLevels.size).toBe(0); + expect($isMaskDrawing()).toBe(false); + }); + + it("test case1", () => + { + vi.mock("../../WebGLUtil.ts", async (importOriginal) => + { + const mod = await importOriginal(); + return { + ...mod, + $gl: { + "createTexture": vi.fn(() => { return "createTexture" }), + "activeTexture": vi.fn(() => { return "activeTexture" }), + "bindTexture": vi.fn(() => { return "bindTexture" }), + "texParameteri": vi.fn(() => { return "texParameteri" }), + "texStorage2D": vi.fn(() => { return "texStorage2D" }), + "createRenderbuffer": vi.fn(() => { return "createRenderbuffer" }), + "bindRenderbuffer": vi.fn(() => { return "bindRenderbuffer" }), + "renderbufferStorage": vi.fn(() => { return "renderbufferStorage" }), + "createProgram": vi.fn(() => { return "createProgram" }), + "createShader": vi.fn(() => { return "createShader" }), + "shaderSource": vi.fn(() => { return "shaderSource" }), + "compileShader": vi.fn(() => { return "compileShader" }), + "attachShader": vi.fn(() => { return "attachShader" }), + "linkProgram": vi.fn(() => { return "linkProgram" }), + "detachShader": vi.fn(() => { return "detachShader" }), + "deleteShader": vi.fn(() => { return "deleteShader" }), + "createVertexArray": vi.fn(() => { return "createVertexArray" }), + "createBuffer": vi.fn(() => { return "createBuffer" }), + "enableVertexAttribArray": vi.fn(() => { return "enableVertexAttribArray" }), + "vertexAttribPointer": vi.fn(() => { return "vertexAttribPointer" }), + "bindVertexArray": vi.fn(() => { return "bindVertexArray" }), + "useProgram": vi.fn(() => { return "useProgram" }), + "bindBuffer": vi.fn(() => { return "bindBuffer" }), + "bufferData": vi.fn(() => { return "bufferData" }), + "drawArrays": vi.fn(() => { return "drawArrays" }), + "blendFunc": vi.fn(() => { return "blendFunc" }), + "getProgramParameter": vi.fn(() => { return 0 }), + "enable": vi.fn((cap) => + { + expect(cap).toBe("SCISSOR_TEST"); + }), + "disable": vi.fn(), + "stencilFunc": vi.fn((func, ref, mask) => + { + switch (func) { + case "ALWAYS": + case "EQUAL": + break; + default: + throw new Error("Invalid func"); + } + switch (mask) { + case 0xff: + case 0x3: + break; + default: + throw new Error("Invalid mask"); + } + switch (ref) { + case 0: + case 3: + case 0xff: + break; + default: + throw new Error("Invalid ref"); + } + }), + "stencilOp": vi.fn((fail, zfail, zpass) => + { + switch (fail) { + case "REPLACE": + case "KEEP": + break; + default: + throw new Error("Invalid fail"); + } + switch (zfail) { + case "REPLACE": + case "KEEP": + break; + default: + throw new Error("Invalid zfail"); + } + switch (zpass) { + case "REPLACE": + case "KEEP": + break; + default: + throw new Error("Invalid zpass"); + } + }), + "colorMask": vi.fn(), + "stencilMask": vi.fn((mask) => + { + switch (mask) { + case 0xff: + case 0x4: + break; + default: + throw new Error("Invalid mask"); + } + }), + "scissor": vi.fn(), + "clear": vi.fn(), + "STENCIL_TEST": "STENCIL_TEST", + "SAMPLE_ALPHA_TO_COVERAGE": "SAMPLE_ALPHA_TO_COVERAGE", + "ALWAYS": "ALWAYS", + "EQUAL": "EQUAL", + "ZERO": "ZERO", + "KEEP": "KEEP", + "REPLACE": "REPLACE", + "INVERT": "INVERT", + "LEQUAL": "LEQUAL", + "SCISSOR_TEST": "SCISSOR_TEST", + "STENCIL_BUFFER_BIT": "STENCIL_BUFFER_BIT", + }, + "$context": { + get currentAttachmentObject() { + return $getCurrentAttachment(); + } + } + } + }); + + const attachmentObject = { + "width": 100, + "height": 100, + "clipLevel": 3, + "msaa": false, + "mask": true, + "color": null, + "texture": { + "id": 0, + "resource": "createTexture", + "width": 100, + "height": 100, + "area": 100 * 100, + "smooth": false + }, + "stencil": { + "id": 0, + "resource": "createRenderbuffer", + "width": 100, + "height": 100, + "area": 100 * 100, + "dirty": false, + } + } as unknown as IAttachmentObject; + $setCurrentAttachment(attachmentObject); + + $clipBounds.set(3, new Float32Array([10, 20, 30, 40])); + $clipBounds.set(2, new Float32Array([10, 20, 30, 40])); + $clipBounds.set(1, new Float32Array([10, 20, 30, 40])); + expect($clipBounds.size).toBe(3); + + $clipLevels.set(3, 3); + $clipLevels.set(2, 2); + $clipLevels.set(1, 1); + expect($clipLevels.size).toBe(3); + + $setMaskDrawing(true); + expect($isMaskDrawing()).toBe(true); + + execute(); + + expect($clipBounds.size).toBe(2); + expect($clipLevels.size).toBe(2); + expect($isMaskDrawing()).toBe(true); + }); +}); \ No newline at end of file From a144eff71b7aa88d65e18fd0ad23f1aab1c6199a Mon Sep 17 00:00:00 2001 From: ienaga Date: Fri, 4 Apr 2025 21:40:50 +0900 Subject: [PATCH 05/13] #175 add UnitTest(@next2d/webgl)(WIP) --- .../MeshCalculateNormalVectorService.test.ts | 12 ++++++ ...eshCalculateNormalizeBezierService.test.ts | 17 ++++++++ .../MeshFindOverlappingPathsService.test.ts | 27 ++++++++++++ ...shGenerateCalculateRoundCapService.test.ts | 43 +++++++++++++++++++ ...hGenerateCalculateSquareCapService.test.ts | 32 ++++++++++++++ ...MeshGetQuadraticBezierPointService.test.ts | 11 +++++ ...shGetQuadraticBezierTangentService.test.ts | 11 +++++ .../src/Mesh/service/MeshLerpService.test.ts | 11 +++++ 8 files changed, 164 insertions(+) create mode 100644 packages/webgl/src/Mesh/service/MeshCalculateNormalVectorService.test.ts create mode 100644 packages/webgl/src/Mesh/service/MeshCalculateNormalizeBezierService.test.ts create mode 100644 packages/webgl/src/Mesh/service/MeshFindOverlappingPathsService.test.ts create mode 100644 packages/webgl/src/Mesh/service/MeshGenerateCalculateRoundCapService.test.ts create mode 100644 packages/webgl/src/Mesh/service/MeshGenerateCalculateSquareCapService.test.ts create mode 100644 packages/webgl/src/Mesh/service/MeshGetQuadraticBezierPointService.test.ts create mode 100644 packages/webgl/src/Mesh/service/MeshGetQuadraticBezierTangentService.test.ts create mode 100644 packages/webgl/src/Mesh/service/MeshLerpService.test.ts diff --git a/packages/webgl/src/Mesh/service/MeshCalculateNormalVectorService.test.ts b/packages/webgl/src/Mesh/service/MeshCalculateNormalVectorService.test.ts new file mode 100644 index 00000000..83e4b5d0 --- /dev/null +++ b/packages/webgl/src/Mesh/service/MeshCalculateNormalVectorService.test.ts @@ -0,0 +1,12 @@ +import { execute } from "./MeshCalculateNormalVectorService"; +import { describe, expect, it } from "vitest"; + +describe("MeshCalculateNormalVectorService.js method test", () => +{ + it("test case", () => + { + const point = execute(10, 20, 5); + expect(point.x).toBe(-4.47213595499958); + expect(point.y).toBe(2.23606797749979); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mesh/service/MeshCalculateNormalizeBezierService.test.ts b/packages/webgl/src/Mesh/service/MeshCalculateNormalizeBezierService.test.ts new file mode 100644 index 00000000..6cce8343 --- /dev/null +++ b/packages/webgl/src/Mesh/service/MeshCalculateNormalizeBezierService.test.ts @@ -0,0 +1,17 @@ +import { execute } from "./MeshCalculateNormalizeBezierService"; +import { describe, expect, it } from "vitest"; +import type { IPoint } from "../../interface/IPoint"; + +describe("MeshCalculateNormalizeBezierService.js method test", () => +{ + it("test case", () => + { + const point: IPoint = { "x": 3, "y": 4 }; + expect(point.x).toBe(3); + expect(point.y).toBe(4); + + const result = execute(point); + expect(result.x).toBe(0.6); + expect(result.y).toBe(0.8); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mesh/service/MeshFindOverlappingPathsService.test.ts b/packages/webgl/src/Mesh/service/MeshFindOverlappingPathsService.test.ts new file mode 100644 index 00000000..9d292b9c --- /dev/null +++ b/packages/webgl/src/Mesh/service/MeshFindOverlappingPathsService.test.ts @@ -0,0 +1,27 @@ +import { execute } from "./MeshFindOverlappingPathsService"; +import { describe, expect, it } from "vitest"; + +describe("MeshFindOverlappingPathsService.js method test", () => +{ + it("test case", () => + { + const paths = [ + 0, 0, false, + 10, 0, false, + 20, 0, false, + 30, 0, false, + 40, 0, false, + 50, 0, false, + 60, 0, false, + 70, 0, false, + 80, 0, false, + 90, 0, false, + 100, 0, false, + 110, 0, false, + 120, 0, false, + 130, 0, false + ]; + const points = execute(0, 0, 0, paths); + expect(points.length).toBe(2); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mesh/service/MeshGenerateCalculateRoundCapService.test.ts b/packages/webgl/src/Mesh/service/MeshGenerateCalculateRoundCapService.test.ts new file mode 100644 index 00000000..d4717772 --- /dev/null +++ b/packages/webgl/src/Mesh/service/MeshGenerateCalculateRoundCapService.test.ts @@ -0,0 +1,43 @@ +import { execute } from "./MeshGenerateCalculateRoundCapService"; +import { describe, expect, it } from "vitest"; + +describe("MeshGenerateCalculateRoundCapService.js method test", () => +{ + it("test case", () => + { + const vertices = [ + 0, 0, false, + 0, 100, false, + 100, 100, false, + 100, 0, false, + 90, 0, false, + 100, -10, false, + 0, 0, false, + ]; + const r = 10; + const rectangles: number[][] = []; + + execute(vertices, r, rectangles); + + expect(rectangles.length).toBe(2); + expect(rectangles[0]).toEqual([ + 10, 0, false, + 9.807852804032304, -1.9509032201612824, false, + 9.238795325112868, -3.826834323650898, false, + 8.314696123025453, -5.555702330196022, false, + 7.0710678118654755, -7.071067811865475, false, + 5.555702330196023, -8.314696123025453, false, + 3.8268343236508984, -9.238795325112868, false, + 1.9509032201612833, -9.807852804032304, false, + 6.123233995736766e-16, -10, false, + -1.950903220161282, -9.807852804032304, false, + -3.826834323650897, -9.238795325112868, false, + -5.55570233019602, -8.314696123025453, false, + -7.071067811865475, -7.0710678118654755, false, + -8.314696123025453, -5.555702330196022, false, + -9.238795325112868, -3.826834323650899, false, + -9.807852804032304, -1.9509032201612861, false, + -10, -1.2246467991473533e-15, false + ]); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mesh/service/MeshGenerateCalculateSquareCapService.test.ts b/packages/webgl/src/Mesh/service/MeshGenerateCalculateSquareCapService.test.ts new file mode 100644 index 00000000..d095cb94 --- /dev/null +++ b/packages/webgl/src/Mesh/service/MeshGenerateCalculateSquareCapService.test.ts @@ -0,0 +1,32 @@ +import { execute } from "./MeshGenerateCalculateSquareCapService"; +import { describe, expect, it } from "vitest"; + +describe("MeshGenerateCalculateSquareCapService.js method test", () => +{ + it("test case", () => + { + const vertices = [ + 0, 0, false, + 0, 100, false, + 100, 100, false, + 100, 0, false, + 90, 0, false, + 100, -10, false, + 0, 0, false, + ]; + const r = 10; + const rectangles: number[][] = []; + + execute(vertices, r, rectangles); + + expect(rectangles.length).toBe(2); + expect(rectangles[0]).toEqual([ + 10, -20, false, + -10, -20, false, + -10, 0, false, + 10, -20, false, + -10, 0, false, + 10, 0, false, + ]); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mesh/service/MeshGetQuadraticBezierPointService.test.ts b/packages/webgl/src/Mesh/service/MeshGetQuadraticBezierPointService.test.ts new file mode 100644 index 00000000..001aae4d --- /dev/null +++ b/packages/webgl/src/Mesh/service/MeshGetQuadraticBezierPointService.test.ts @@ -0,0 +1,11 @@ +import { execute } from "./MeshGetQuadraticBezierPointService"; +import { describe, expect, it } from "vitest"; + +describe("MeshGetQuadraticBezierPointService.js method test", () => +{ + it("test case", () => + { + expect(execute(10, { x: 11, y: 0.7 }, { x: 1.3, y: 12 }, { x: 29, y: 32 })) + .toEqual({ x: 3557, y: 1096.6999999999998 }); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mesh/service/MeshGetQuadraticBezierTangentService.test.ts b/packages/webgl/src/Mesh/service/MeshGetQuadraticBezierTangentService.test.ts new file mode 100644 index 00000000..3d2da5a7 --- /dev/null +++ b/packages/webgl/src/Mesh/service/MeshGetQuadraticBezierTangentService.test.ts @@ -0,0 +1,11 @@ +import { execute } from "./MeshGetQuadraticBezierTangentService"; +import { describe, expect, it } from "vitest"; + +describe("MeshGetQuadraticBezierTangentService.js method test", () => +{ + it("test case", () => + { + expect(execute(10, { x: 11, y: 0.7 }, { x: 1.3, y: 12 }, { x: 29, y: 32 })) + .toEqual({ x: 728.6, y: 196.6 }); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mesh/service/MeshLerpService.test.ts b/packages/webgl/src/Mesh/service/MeshLerpService.test.ts new file mode 100644 index 00000000..09ba2159 --- /dev/null +++ b/packages/webgl/src/Mesh/service/MeshLerpService.test.ts @@ -0,0 +1,11 @@ +import { execute } from "./MeshLerpService"; +import { describe, expect, it } from "vitest"; + +describe("MeshLerpService.js method test", () => +{ + it("test case", () => + { + expect(execute({ x: 1.2, y: 0.9 }, { x: 10.8, y: 56.1 }, 0.332)) + .toEqual({ x: 4.387200000000001, y: 19.2264 }); + }); +}); \ No newline at end of file From 4872305e481f1e16babe5418d75ce42d7b14e2c0 Mon Sep 17 00:00:00 2001 From: ienaga Date: Fri, 4 Apr 2025 22:20:05 +0900 Subject: [PATCH 06/13] #175 add UnitTest(@next2d/webgl) --- ...hApproximateOffsetQuadraticUseCase.test.ts | 22 ++ ...MeshCalculateCurveRectangleUseCase.test.ts | 330 ++++++++++++++++++ .../MeshCalculateLineRectangleUseCase.test.ts | 16 + ...eshSplitBezierMultipleTimesUseCase.test.ts | 93 +++++ .../MeshSplitQuadraticBezierUseCase.test.ts | 14 + 5 files changed, 475 insertions(+) create mode 100644 packages/webgl/src/Mesh/usecase/MeshApproximateOffsetQuadraticUseCase.test.ts create mode 100644 packages/webgl/src/Mesh/usecase/MeshCalculateCurveRectangleUseCase.test.ts create mode 100644 packages/webgl/src/Mesh/usecase/MeshCalculateLineRectangleUseCase.test.ts create mode 100644 packages/webgl/src/Mesh/usecase/MeshSplitBezierMultipleTimesUseCase.test.ts create mode 100644 packages/webgl/src/Mesh/usecase/MeshSplitQuadraticBezierUseCase.test.ts diff --git a/packages/webgl/src/Mesh/usecase/MeshApproximateOffsetQuadraticUseCase.test.ts b/packages/webgl/src/Mesh/usecase/MeshApproximateOffsetQuadraticUseCase.test.ts new file mode 100644 index 00000000..f50b0aaf --- /dev/null +++ b/packages/webgl/src/Mesh/usecase/MeshApproximateOffsetQuadraticUseCase.test.ts @@ -0,0 +1,22 @@ +import { execute } from "./MeshApproximateOffsetQuadraticUseCase"; +import { describe, expect, it } from "vitest"; +import type { IPoint } from "../../interface/IPoint"; + +describe("MeshApproximateOffsetQuadraticUseCase.js method test", () => +{ + it("test case", () => + { + const s0: IPoint = { "x": 0, "y": 0 }; + const s1: IPoint = { "x": 1, "y": 1 }; + const s2: IPoint = { "x": 2, "y": 0 }; + const offset = 1; + + const result = execute(s0, s1, s2, offset); + + expect(result).toEqual([ + { "x": -0.7071067811865475, "y": 0.7071067811865475 }, + { "x": 1, "y": 1.5 }, + { "x": 2.7071067811865475, "y": 0.7071067811865475 } + ]); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mesh/usecase/MeshCalculateCurveRectangleUseCase.test.ts b/packages/webgl/src/Mesh/usecase/MeshCalculateCurveRectangleUseCase.test.ts new file mode 100644 index 00000000..30710371 --- /dev/null +++ b/packages/webgl/src/Mesh/usecase/MeshCalculateCurveRectangleUseCase.test.ts @@ -0,0 +1,330 @@ +import { execute } from "./MeshCalculateCurveRectangleUseCase"; +import { describe, expect, it } from "vitest"; +import type { IPoint } from "../../interface/IPoint"; + +describe("MeshCalculateCurveRectangleUseCase.js method test", () => +{ + it("test case", () => + { + const paths = execute({ x: 90, y: 120 }, { x: 91, y: 30 }, { x: 210, y: 100 }, 3); + console.log(paths); + expect(paths).toEqual([ + 92.99981483195982, 120.03333127591067, false, + 93.05847547276832, 117.3240110485681, true, + 93.17318295655153, 114.69644017912968, + false, 93.34367026233961, 112.15082173105502, true, + 93.56963219245895, 109.68735553811679, false, 93.85072148852632, + 107.30623263017817, true, 94.1865452260656, 105.00762801604638, + false, 94.57666184035824, 102.79169154406925, true, + 95.02057926829268, 100.65853658536585, false, 95.51775484509592, + 98.60822635509618, true, 96.06759776086137, 96.64075782500278, + false, 96.66947503891528, 94.75604340895377, true, + 97.32272211068204, 92.95389094370037, false, 98.02665907650476, + 91.23398295079949, true, 98.78061358848315, 89.59585674157303, + false, 99.58395089022275, 88.03888756599137, true, + 100.43611082961729, 86.56227760606654, false, 101.33665059664483, + 85.16505401183957, true, 102.28529058535305, 83.84607916258767, + false, 103.28195931875285, 82.60407569277815, true, + 104.32683212636016, 81.43766741183478, false, 105.42035764347963, + 80.3454351028803, true, 106.56326661234834, 79.32598359435116, + false, 107.75655913230267, 78.37801400052852, true, + 109.00146931659933, 77.50039330253732, false, 110.29940975721478, + 76.69221308618341, true, 111.65190147232951, 75.9528305305225, + false, 113.06049727545003, 75.28188743265633, true, + 114.52670719235728, 74.67930650301508, false, 116.05193357124341, + 74.14526750807323, true, 117.63742127341362, 73.68016831446116, + false, 119.28422548424233, 73.28457708301556, true, + 120.99319696191607, 72.95918177149643, false, 122.76498246545046, + 72.70474205039667, + true, + 124.60003690142062, + 72.52204718028263, + false, + 126.49864336287645, + 72.41188177635226, + true, + 128.4609375, + 72.375, + false, + 130.4869333010182, + 72.41210771438614, + true, + 132.57654814099826, + 72.5238515382499, + false, + 134.72962570923485, + 72.71081346697419, + true, + 136.9459560591959, + 72.97350970751056, + false, + 139.22529250334242, + 73.31239250022244, + true, + 141.5673654021229, + 73.72785389983642, + false, + 143.97189309579554, + 74.22023070624105, + true, + 146.4385903300649, + 74.78980994154595, + false, + 148.9671745613114, + 75.43683444640628, + true, + 151.5573705189908, + 76.16150831075156, + false, + 154.20891337013802, + 76.96400196276316, + true, + 156.9215507867719, + 77.8444568194639, + false, + 159.6950441697604, + 78.80298945800155, + true, + 162.52916923735802, + 79.83969530397181, + false, + 165.42371614579625, + 80.95465185664783, + true, + 168.3784892740845, + 82.14792148463907, + false, + 171.3933067757061, + 83.41955383231668, + true, + 174.4679999758045, + 84.76958787959106, + false, + 177.60241267312426, + 86.19805369696745, + true, + 180.79640039069227, + 87.7049739354066, + false, + 184.04982960730766, + 89.29036508718556, + true, + 187.3625769927208, + 90.95423855022293, + false, + 190.73452866237673, + 92.69660152454583, + true, + 194.16557946231575, + 94.51745776594173, + false, + 197.65563229088735, + 96.41680821847216, + true, + 201.20459746103566, + 98.39465154448482, + false, + 204.81239210481624, + 100.45098456806144, + true, + 208.47893962030983, + 102.58580264547331, + false, + 211.52106037969017, + 97.41419735452669, + false, + 207.80772508268376, + 95.25214043193856, + true, + 204.15087128896434, + 93.16784845551518, + false, + 200.55042239661265, + 91.16131678152784, + true, + 197.00629553768425, + 89.23254223405827, + false, + 193.51840102512327, + 87.38152347545417, + true, + 190.0866417572792, + 85.60826144977707, + false, + 186.71091258019234, + 83.91275991281444, + true, + 183.39109960930773, + 82.2950260645934, + false, + 180.12707951437574, + 80.75507130303255, + true, + 176.9187187741955, + 79.29291212040894, + false, + 173.7658729117939, + 77.90857116768332, + true, + 170.6683857259155, + 76.60207851536093, + false, + 167.62608854170375, + 75.37347314335217, + true, + 164.63879951264198, + 74.22280469602819, + false, + 161.7063230177396, + 73.15013554199845, + true, + 158.8284492132281, + 72.1555431805361, + false, + 156.00495381736198, + 71.23912303723684, + true, + 153.2355982310092, + 70.40099168924844, + false, + 150.5201301261886, + 69.64129055359372, + true, + 147.8582846699351, + 68.96019005845405, + false, + 145.24978659170446, + 68.35789429375895, + true, + 142.6943533478771, + 67.83464610016358, + false, + 140.19169968415758, + 67.39073249977756, + true, + 137.7415439408041, + 67.02649029248944, + false, + 135.34361647826515, + 66.74231153302581, + true, + 132.99767060900174, + 66.5386484617501, + false, + 130.7034963864818, + 66.41601728561386, + true, + 128.4609375, + 66.375, + false, + 126.26991132462355, + 66.41624322364774, + true, + 124.13043184857938, + 66.54045281971737, + false, + 122.04263472204954, + 66.74838294960333, + true, + 120.00680303808393, + 67.04081822850357, + false, + 118.02339170325767, + 67.41854791698444, + true, + 116.09304747658638, + 67.88233168553884, + false, + 114.21662111625659, + 68.43285749192677, + true, + 112.39516780764272, + 69.07069349698492, + false, + 110.62993241204997, + 69.79623756734367, + true, + 108.92231727767049, + 70.6096694694775, + false, + 107.27383243028522, + 71.51091191381659, + true, + 105.68603068340067, + 72.49960669746268, + false, + 104.16043305519733, + 73.57511099947148, + true, + 102.69845213765166, + 74.73651640564884, + false, + 101.30132204402037, + 75.9826898971197, + true, + 99.97004287363984, + 77.31233258816522, + false, + 98.70534536874715, + 78.72404930722185, + true, + 97.50767816464695, + 80.21642083741233, + false, + 96.37721659085517, + 81.78807098816043, + true, + 95.31388917038271, + 83.43772239393346, + false, + 94.31741629727725, + 85.16423743400863, + true, + 93.38735516151685, + 86.96664325842697, + false, + 92.52314561099524, + 88.84414204920051, + true, + 91.72415288931796, + 90.79610905629963, + false, + 90.98970464858472, + 92.82208159104623, + true, + 90.31912098913863, + 94.92174217499722, + false, + 89.71173734240408, + 97.09489864490382, + true, + 89.16692073170732, + 99.34146341463415, + false, + 88.68408034714176, + 101.66143345593075, + true, + 88.2626735239344, + 104.05487198395362, + false, + 87.90220819897368, + 106.52189236982183, + true, + 87.60224280754105, + 109.06264446188321, + false, + 87.36238442516039, + 111.67730326894498, + true, + 87.18228579344847, + 114.36605982087032, + false, + 87.06164171473168, + 117.1291139514319, + true, + 87.00018516804018, + 119.96666872408933, + false, + ]); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mesh/usecase/MeshCalculateLineRectangleUseCase.test.ts b/packages/webgl/src/Mesh/usecase/MeshCalculateLineRectangleUseCase.test.ts new file mode 100644 index 00000000..fdcc9751 --- /dev/null +++ b/packages/webgl/src/Mesh/usecase/MeshCalculateLineRectangleUseCase.test.ts @@ -0,0 +1,16 @@ +import { execute } from "./MeshCalculateLineRectangleUseCase"; +import { describe, expect, it } from "vitest"; + +describe("MeshCalculateLineRectangleUseCase.js method test", () => +{ + it("test case", () => + { + expect(execute({ x: 120, y: 90 }, { x: -231, y: 110 }, 3)).toEqual([ + 119.82933665318774, 87.00485826344482, false, + -231.17066334681226, 107.00485826344482,false, + -230.82933665318774, 112.99514173655518, false, + 120.17066334681226, 92.99514173655518, false, + 119.82933665318774, 87.00485826344482, false + ]); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mesh/usecase/MeshSplitBezierMultipleTimesUseCase.test.ts b/packages/webgl/src/Mesh/usecase/MeshSplitBezierMultipleTimesUseCase.test.ts new file mode 100644 index 00000000..60e0653e --- /dev/null +++ b/packages/webgl/src/Mesh/usecase/MeshSplitBezierMultipleTimesUseCase.test.ts @@ -0,0 +1,93 @@ +import { execute } from "./MeshSplitBezierMultipleTimesUseCase"; +import { describe, expect, it } from "vitest"; +import type { IPoint } from "../../interface/IPoint"; + +describe("MeshSplitBezierMultipleTimesUseCase.js method test", () => +{ + it("test case", () => + { + const segments = execute({ x: 120, y: 90 }, { x: 21, y: 31 }, { x: 333, y: 123 }); + expect(segments).toEqual([ + [ + { x: 120, y: 90 }, + { x: 113.8125, y: 86.3125 }, + { x: 109.23046875, y: 83.21484375 } + ], + [ + { x: 109.23046875, y: 83.21484375 }, + { x: 104.6484375, y: 80.1171875 }, + { x: 101.671875, y: 77.609375 } + ], + [ + { x: 101.671875, y: 77.609375 }, + { x: 98.6953125, y: 75.1015625 }, + { x: 97.32421875, y: 73.18359375 } + ], + [ + { x: 97.32421875, y: 73.18359375 }, + { x: 95.953125, y: 71.265625 }, + { x: 96.1875, y: 69.9375 } + ], + [ + { x: 96.1875, y: 69.9375 }, + { x: 96.421875, y: 68.609375 }, + { x: 98.26171875, y: 67.87109375 } + ], + [ + { x: 98.26171875, y: 67.87109375 }, + { x: 100.1015625, y: 67.1328125 }, + { x: 103.546875, y: 66.984375 } + ], + [ + { x: 103.546875, y: 66.984375 }, + { x: 106.9921875, y: 66.8359375 }, + { x: 112.04296875, y: 67.27734375 } + ], + [ + { x: 112.04296875, y: 67.27734375 }, + { x: 117.09375, y: 67.71875 }, + { x: 123.75, y: 68.75 } + ], + [ + { x: 123.75, y: 68.75 }, + { x: 130.40625, y: 69.78125 }, + { x: 138.66796875, y: 71.40234375 } + ], + [ + { x: 138.66796875, y: 71.40234375 }, + { x: 146.9296875, y: 73.0234375 }, + { x: 156.796875, y: 75.234375 } + ], + [ + { x: 156.796875, y: 75.234375 }, + { x: 166.6640625, y: 77.4453125 }, + { x: 178.13671875, y: 80.24609375 } + ], + [ + { x: 178.13671875, y: 80.24609375 }, + { x: 189.609375, y: 83.046875 }, + { x: 202.6875, y: 86.4375 } + ], + [ + { x: 202.6875, y: 86.4375 }, + { x: 215.765625, y: 89.828125 }, + { x: 230.44921875, y: 93.80859375 } + ], + [ + { x: 230.44921875, y: 93.80859375 }, + { x: 245.1328125, y: 97.7890625 }, + { x: 261.421875, y: 102.359375 } + ], + [ + { x: 261.421875, y: 102.359375 }, + { x: 277.7109375, y: 106.9296875 }, + { x: 295.60546875, y: 112.08984375 } + ], + [ + { x: 295.60546875, y: 112.08984375 }, + { x: 313.5, y: 117.25 }, + { x: 333, y: 123 } + ] + ]); + }); +}); \ No newline at end of file diff --git a/packages/webgl/src/Mesh/usecase/MeshSplitQuadraticBezierUseCase.test.ts b/packages/webgl/src/Mesh/usecase/MeshSplitQuadraticBezierUseCase.test.ts new file mode 100644 index 00000000..c60ac6af --- /dev/null +++ b/packages/webgl/src/Mesh/usecase/MeshSplitQuadraticBezierUseCase.test.ts @@ -0,0 +1,14 @@ +import { execute } from "./MeshSplitQuadraticBezierUseCase"; +import { describe, expect, it } from "vitest"; + +describe("MeshSplitQuadraticBezierUseCase.js method test", () => +{ + it("test case", () => + { + const segments = execute({ x: 120, y: 90 }, { x: 21, y: 31 }, { x: 333, y: 123 }); + expect(segments).toEqual([ + [ { x: 120, y: 90 }, { x: 70.5, y: 60.5 }, { x: 123.75, y: 68.75 } ], + [ { x: 123.75, y: 68.75 }, { x: 177, y: 77 }, { x: 333, y: 123 } ] + ]); + }); +}); \ No newline at end of file From a8b9df25dcceba9ff7d007ce78262a973a0cf66f Mon Sep 17 00:00:00 2001 From: ienaga Date: Fri, 4 Apr 2025 22:21:39 +0900 Subject: [PATCH 07/13] #175 update packages --- package-lock.json | 229 ++++++++++++++++++++++++---------------------- package.json | 6 +- 2 files changed, 124 insertions(+), 111 deletions(-) diff --git a/package-lock.json b/package-lock.json index 088b6a6e..cfff2b31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@next2d/player", - "version": "2.1.2", + "version": "2.1.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@next2d/player", - "version": "2.1.2", + "version": "2.1.3", "license": "MIT", "workspaces": [ "packages/*" @@ -22,7 +22,7 @@ "@rollup/plugin-node-resolve": "^16.0.1", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^12.1.2", - "@types/node": "^22.13.15", + "@types/node": "^22.14.0", "@typescript-eslint/eslint-plugin": "^8.29.0", "@typescript-eslint/parser": "^8.29.0", "@vitest/web-worker": "^3.1.1", @@ -30,10 +30,10 @@ "eslint-plugin-unused-imports": "^4.1.4", "globals": "^16.0.0", "jsdom": "^26.0.0", - "rollup": "^4.38.0", + "rollup": "^4.39.0", "tslib": "^2.8.1", "typescript": "^5.8.2", - "vite": "^6.2.4", + "vite": "^6.2.5", "vitest": "^3.1.1", "vitest-webgl-canvas-mock": "^1.1.0" }, @@ -657,9 +657,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz", - "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.1.tgz", + "integrity": "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -737,19 +737,32 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", - "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", + "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.12.0", + "@eslint/core": "^0.13.0", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -1100,9 +1113,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.38.0.tgz", - "integrity": "sha512-ldomqc4/jDZu/xpYU+aRxo3V4mGCV9HeTgUBANI3oIQMOL+SsxB+S2lxMpkFp5UamSS3XuTMQVbsS24R4J4Qjg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.39.0.tgz", + "integrity": "sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==", "cpu": [ "arm" ], @@ -1114,9 +1127,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.38.0.tgz", - "integrity": "sha512-VUsgcy4GhhT7rokwzYQP+aV9XnSLkkhlEJ0St8pbasuWO/vwphhZQxYEKUP3ayeCYLhk6gEtacRpYP/cj3GjyQ==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.39.0.tgz", + "integrity": "sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==", "cpu": [ "arm64" ], @@ -1128,9 +1141,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.38.0.tgz", - "integrity": "sha512-buA17AYXlW9Rn091sWMq1xGUvWQFOH4N1rqUxGJtEQzhChxWjldGCCup7r/wUnaI6Au8sKXpoh0xg58a7cgcpg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.39.0.tgz", + "integrity": "sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==", "cpu": [ "arm64" ], @@ -1142,9 +1155,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.38.0.tgz", - "integrity": "sha512-Mgcmc78AjunP1SKXl624vVBOF2bzwNWFPMP4fpOu05vS0amnLcX8gHIge7q/lDAHy3T2HeR0TqrriZDQS2Woeg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.39.0.tgz", + "integrity": "sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==", "cpu": [ "x64" ], @@ -1156,9 +1169,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.38.0.tgz", - "integrity": "sha512-zzJACgjLbQTsscxWqvrEQAEh28hqhebpRz5q/uUd1T7VTwUNZ4VIXQt5hE7ncs0GrF+s7d3S4on4TiXUY8KoQA==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.39.0.tgz", + "integrity": "sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==", "cpu": [ "arm64" ], @@ -1170,9 +1183,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.38.0.tgz", - "integrity": "sha512-hCY/KAeYMCyDpEE4pTETam0XZS4/5GXzlLgpi5f0IaPExw9kuB+PDTOTLuPtM10TlRG0U9OSmXJ+Wq9J39LvAg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.39.0.tgz", + "integrity": "sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==", "cpu": [ "x64" ], @@ -1184,9 +1197,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.38.0.tgz", - "integrity": "sha512-mimPH43mHl4JdOTD7bUMFhBdrg6f9HzMTOEnzRmXbOZqjijCw8LA5z8uL6LCjxSa67H2xiLFvvO67PT05PRKGg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.39.0.tgz", + "integrity": "sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==", "cpu": [ "arm" ], @@ -1198,9 +1211,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.38.0.tgz", - "integrity": "sha512-tPiJtiOoNuIH8XGG8sWoMMkAMm98PUwlriOFCCbZGc9WCax+GLeVRhmaxjJtz6WxrPKACgrwoZ5ia/uapq3ZVg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.39.0.tgz", + "integrity": "sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==", "cpu": [ "arm" ], @@ -1212,9 +1225,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.38.0.tgz", - "integrity": "sha512-wZco59rIVuB0tjQS0CSHTTUcEde+pXQWugZVxWaQFdQQ1VYub/sTrNdY76D1MKdN2NB48JDuGABP6o6fqos8mA==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.39.0.tgz", + "integrity": "sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==", "cpu": [ "arm64" ], @@ -1226,9 +1239,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.38.0.tgz", - "integrity": "sha512-fQgqwKmW0REM4LomQ+87PP8w8xvU9LZfeLBKybeli+0yHT7VKILINzFEuggvnV9M3x1Ed4gUBmGUzCo/ikmFbQ==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.39.0.tgz", + "integrity": "sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==", "cpu": [ "arm64" ], @@ -1240,9 +1253,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.38.0.tgz", - "integrity": "sha512-hz5oqQLXTB3SbXpfkKHKXLdIp02/w3M+ajp8p4yWOWwQRtHWiEOCKtc9U+YXahrwdk+3qHdFMDWR5k+4dIlddg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.39.0.tgz", + "integrity": "sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==", "cpu": [ "loong64" ], @@ -1254,9 +1267,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.38.0.tgz", - "integrity": "sha512-NXqygK/dTSibQ+0pzxsL3r4Xl8oPqVoWbZV9niqOnIHV/J92fe65pOir0xjkUZDRSPyFRvu+4YOpJF9BZHQImw==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.39.0.tgz", + "integrity": "sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==", "cpu": [ "ppc64" ], @@ -1268,9 +1281,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.38.0.tgz", - "integrity": "sha512-GEAIabR1uFyvf/jW/5jfu8gjM06/4kZ1W+j1nWTSSB3w6moZEBm7iBtzwQ3a1Pxos2F7Gz+58aVEnZHU295QTg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.39.0.tgz", + "integrity": "sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==", "cpu": [ "riscv64" ], @@ -1282,9 +1295,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.38.0.tgz", - "integrity": "sha512-9EYTX+Gus2EGPbfs+fh7l95wVADtSQyYw4DfSBcYdUEAmP2lqSZY0Y17yX/3m5VKGGJ4UmIH5LHLkMJft3bYoA==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.39.0.tgz", + "integrity": "sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==", "cpu": [ "riscv64" ], @@ -1296,9 +1309,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.38.0.tgz", - "integrity": "sha512-Mpp6+Z5VhB9VDk7RwZXoG2qMdERm3Jw07RNlXHE0bOnEeX+l7Fy4bg+NxfyN15ruuY3/7Vrbpm75J9QHFqj5+Q==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.39.0.tgz", + "integrity": "sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==", "cpu": [ "s390x" ], @@ -1310,9 +1323,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.38.0.tgz", - "integrity": "sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.39.0.tgz", + "integrity": "sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==", "cpu": [ "x64" ], @@ -1324,9 +1337,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.38.0.tgz", - "integrity": "sha512-q5Zv+goWvQUGCaL7fU8NuTw8aydIL/C9abAVGCzRReuj5h30TPx4LumBtAidrVOtXnlB+RZkBtExMsfqkMfb8g==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.39.0.tgz", + "integrity": "sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==", "cpu": [ "x64" ], @@ -1338,9 +1351,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.38.0.tgz", - "integrity": "sha512-u/Jbm1BU89Vftqyqbmxdq14nBaQjQX1HhmsdBWqSdGClNaKwhjsg5TpW+5Ibs1mb8Es9wJiMdl86BcmtUVXNZg==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.39.0.tgz", + "integrity": "sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==", "cpu": [ "arm64" ], @@ -1352,9 +1365,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.38.0.tgz", - "integrity": "sha512-mqu4PzTrlpNHHbu5qleGvXJoGgHpChBlrBx/mEhTPpnAL1ZAYFlvHD7rLK839LLKQzqEQMFJfGrrOHItN4ZQqA==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.39.0.tgz", + "integrity": "sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==", "cpu": [ "ia32" ], @@ -1366,9 +1379,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.38.0.tgz", - "integrity": "sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.39.0.tgz", + "integrity": "sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==", "cpu": [ "x64" ], @@ -1394,13 +1407,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.15.tgz", - "integrity": "sha512-imAbQEEbVni6i6h6Bd5xkCRwLqFc8hihCsi2GbtDoAtUcAFQ6Zs4pFXTZUUbroTkXdImczWM9AI8eZUuybXE3w==", + "version": "22.14.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.0.tgz", + "integrity": "sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/resolve": { @@ -3633,9 +3646,9 @@ } }, "node_modules/rollup": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.38.0.tgz", - "integrity": "sha512-5SsIRtJy9bf1ErAOiFMFzl64Ex9X5V7bnJ+WlFMb+zmP459OSWCEG7b0ERZ+PEU7xPt4OG3RHbrp1LJlXxYTrw==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.39.0.tgz", + "integrity": "sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==", "dev": true, "license": "MIT", "dependencies": { @@ -3649,26 +3662,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.38.0", - "@rollup/rollup-android-arm64": "4.38.0", - "@rollup/rollup-darwin-arm64": "4.38.0", - "@rollup/rollup-darwin-x64": "4.38.0", - "@rollup/rollup-freebsd-arm64": "4.38.0", - "@rollup/rollup-freebsd-x64": "4.38.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.38.0", - "@rollup/rollup-linux-arm-musleabihf": "4.38.0", - "@rollup/rollup-linux-arm64-gnu": "4.38.0", - "@rollup/rollup-linux-arm64-musl": "4.38.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.38.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.38.0", - "@rollup/rollup-linux-riscv64-gnu": "4.38.0", - "@rollup/rollup-linux-riscv64-musl": "4.38.0", - "@rollup/rollup-linux-s390x-gnu": "4.38.0", - "@rollup/rollup-linux-x64-gnu": "4.38.0", - "@rollup/rollup-linux-x64-musl": "4.38.0", - "@rollup/rollup-win32-arm64-msvc": "4.38.0", - "@rollup/rollup-win32-ia32-msvc": "4.38.0", - "@rollup/rollup-win32-x64-msvc": "4.38.0", + "@rollup/rollup-android-arm-eabi": "4.39.0", + "@rollup/rollup-android-arm64": "4.39.0", + "@rollup/rollup-darwin-arm64": "4.39.0", + "@rollup/rollup-darwin-x64": "4.39.0", + "@rollup/rollup-freebsd-arm64": "4.39.0", + "@rollup/rollup-freebsd-x64": "4.39.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.39.0", + "@rollup/rollup-linux-arm-musleabihf": "4.39.0", + "@rollup/rollup-linux-arm64-gnu": "4.39.0", + "@rollup/rollup-linux-arm64-musl": "4.39.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.39.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.39.0", + "@rollup/rollup-linux-riscv64-gnu": "4.39.0", + "@rollup/rollup-linux-riscv64-musl": "4.39.0", + "@rollup/rollup-linux-s390x-gnu": "4.39.0", + "@rollup/rollup-linux-x64-gnu": "4.39.0", + "@rollup/rollup-linux-x64-musl": "4.39.0", + "@rollup/rollup-win32-arm64-msvc": "4.39.0", + "@rollup/rollup-win32-ia32-msvc": "4.39.0", + "@rollup/rollup-win32-x64-msvc": "4.39.0", "fsevents": "~2.3.2" } }, @@ -3843,9 +3856,9 @@ "license": "MIT" }, "node_modules/std-env": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.1.tgz", - "integrity": "sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", "dev": true, "license": "MIT" }, @@ -4065,9 +4078,9 @@ } }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -4082,9 +4095,9 @@ } }, "node_modules/vite": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz", - "integrity": "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==", + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.5.tgz", + "integrity": "sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index a4bf73e2..fd880363 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "@rollup/plugin-node-resolve": "^16.0.1", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^12.1.2", - "@types/node": "^22.13.15", + "@types/node": "^22.14.0", "@typescript-eslint/eslint-plugin": "^8.29.0", "@typescript-eslint/parser": "^8.29.0", "@vitest/web-worker": "^3.1.1", @@ -59,10 +59,10 @@ "eslint-plugin-unused-imports": "^4.1.4", "globals": "^16.0.0", "jsdom": "^26.0.0", - "rollup": "^4.38.0", + "rollup": "^4.39.0", "tslib": "^2.8.1", "typescript": "^5.8.2", - "vite": "^6.2.4", + "vite": "^6.2.5", "vitest": "^3.1.1", "vitest-webgl-canvas-mock": "^1.1.0" }, From a6ef776a7a2f8d33137cff01d579d85f33b4ea9a Mon Sep 17 00:00:00 2001 From: ienaga Date: Sat, 5 Apr 2025 10:52:19 +0900 Subject: [PATCH 08/13] =?UTF-8?q?#175=20=E3=82=B3=E3=83=A1=E3=83=B3?= =?UTF-8?q?=E3=83=88=E3=82=92=E8=BF=BD=E8=A8=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../text/src/TextArea/usecase/TextAreaRegisterEventUseCase.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/text/src/TextArea/usecase/TextAreaRegisterEventUseCase.ts b/packages/text/src/TextArea/usecase/TextAreaRegisterEventUseCase.ts index d6572299..394b4a94 100644 --- a/packages/text/src/TextArea/usecase/TextAreaRegisterEventUseCase.ts +++ b/packages/text/src/TextArea/usecase/TextAreaRegisterEventUseCase.ts @@ -14,7 +14,7 @@ import { execute as textAreaInputUseCase } from "./TextAreaInputUseCase"; */ export const execute = (text_area: HTMLTextAreaElement): void => { - // omposition evnet + // composition evnet text_area.addEventListener("compositionstart", textAreaCompositionStartUseCase as EventListener); text_area.addEventListener("compositionupdate", textAreaCompositionUpdateUseCase as EventListener); text_area.addEventListener("compositionend", textAreaCompositionEndUseCase as EventListener); From e3fceae44f27d335d044c420de47b6f2f8f3815d Mon Sep 17 00:00:00 2001 From: ienaga Date: Sat, 5 Apr 2025 10:52:45 +0900 Subject: [PATCH 09/13] =?UTF-8?q?#175=20change=E3=82=A4=E3=83=99=E3=83=B3?= =?UTF-8?q?=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/events/src/Event.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/events/src/Event.ts b/packages/events/src/Event.ts index b3f86a53..7d308d7f 100644 --- a/packages/events/src/Event.ts +++ b/packages/events/src/Event.ts @@ -187,6 +187,19 @@ export class Event return "addedToStage"; } + /** + * @description 要素の値を変更したときに発行されます。 + * Occurs when the value of an element changes. + * + * @return {string} + * @const + * @static + */ + static get CHANGE (): string + { + return "change"; + } + /** * @description 読み込みや、処理完了時に発生します。 * Occurs when loading or processing is complete. From 0d296298dff29cfa024cf4ae64efd0f37cbb7789 Mon Sep 17 00:00:00 2001 From: ienaga Date: Sat, 5 Apr 2025 10:53:10 +0900 Subject: [PATCH 10/13] =?UTF-8?q?#175=20change=E3=82=A4=E3=83=99=E3=83=B3?= =?UTF-8?q?=E3=83=88=E3=81=AE=E7=99=BA=E7=81=AB=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/text/src/TextField.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/text/src/TextField.ts b/packages/text/src/TextField.ts index a1f859b7..f445ef91 100644 --- a/packages/text/src/TextField.ts +++ b/packages/text/src/TextField.ts @@ -4,7 +4,7 @@ import type { ITextFieldType } from "./interface/ITextFieldType"; import type { ITextFieldCharacter } from "./interface/ITextFieldCharacter"; import type { ICharacter } from "./interface/ICharacter"; import type { LoaderInfo } from "@next2d/display"; -import { FocusEvent } from "@next2d/events"; +import { FocusEvent, Event } from "@next2d/events"; import { Rectangle } from "@next2d/geom"; import { TextData } from "./TextData"; import { TextFormat } from "./TextFormat"; @@ -854,6 +854,10 @@ export class TextField extends InteractiveObject this._$text = ""; this._$isHTML = true; textFieldReloadUseCase(this); + + if (this.hasEventListener(Event.CHANGE)) { + this.dispatchEvent(new Event(Event.CHANGE)); + } } /** @@ -978,6 +982,10 @@ export class TextField extends InteractiveObject this._$text = text; textFieldReloadUseCase(this); + + if (this.hasEventListener(Event.CHANGE)) { + this.dispatchEvent(new Event(Event.CHANGE)); + } } /** From 1efc748f50e4345d9a4feb766adfa7a5fa9eeca7 Mon Sep 17 00:00:00 2001 From: ienaga Date: Sat, 5 Apr 2025 10:53:43 +0900 Subject: [PATCH 11/13] =?UTF-8?q?#175=20=E4=BA=92=E3=81=84=E5=8F=82?= =?UTF-8?q?=E7=85=A7=E3=82=92=E7=B7=A9=E5=92=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/text/src/TextUtil.ts | 2 -- packages/text/src/index.ts | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/text/src/TextUtil.ts b/packages/text/src/TextUtil.ts index 1db78af5..c2afeebe 100644 --- a/packages/text/src/TextUtil.ts +++ b/packages/text/src/TextUtil.ts @@ -1,7 +1,6 @@ import type { IRGBA } from "./interface/IRGBA"; import type { IElementPosition } from "./interface/IElementPosition"; import type { TextField } from "./TextField"; -import { execute as textAreaRegisterEventUseCase } from "./TextArea/usecase/TextAreaRegisterEventUseCase"; /** * @description 選択中のテキストフィールド @@ -46,7 +45,6 @@ export const $getSelectedTextField = (): TextField | null => * @protected */ export const $textArea: HTMLTextAreaElement = document.createElement("textarea") as HTMLTextAreaElement; -textAreaRegisterEventUseCase($textArea); $textArea.tabIndex = -1; diff --git a/packages/text/src/index.ts b/packages/text/src/index.ts index 154c93ad..9683a943 100644 --- a/packages/text/src/index.ts +++ b/packages/text/src/index.ts @@ -5,4 +5,8 @@ export { $getSelectedTextField, $setSelectedTextField, $mainCanvasPosition -} from "./TextUtil"; \ No newline at end of file +} from "./TextUtil"; + +import { $textArea } from "./TextUtil"; +import { execute as textAreaRegisterEventUseCase } from "./TextArea/usecase/TextAreaRegisterEventUseCase"; +textAreaRegisterEventUseCase($textArea); \ No newline at end of file From faa5e168dbde7e0d5ca07bcb8d6b4c390d8c2b89 Mon Sep 17 00:00:00 2001 From: ienaga Date: Sat, 5 Apr 2025 10:54:06 +0900 Subject: [PATCH 12/13] =?UTF-8?q?#175=20=E3=83=90=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E6=83=85=E5=A0=B1=E3=82=92=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 52a4515a..51c07a5d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ import { Next2D } from "@next2d/core"; if (!("next2d" in window)) { - console.log("%c Next2D Player %c 2.1.1 %c https://next2d.app", + console.log("%c Next2D Player %c 2.1.3 %c https://next2d.app", "color: #fff; background: #5f5f5f", "color: #fff; background: #4bc729", ""); From 98e4737ff2b1b81ab03e5eccad8c49ff5ab0e3a1 Mon Sep 17 00:00:00 2001 From: ienaga Date: Sat, 5 Apr 2025 10:54:41 +0900 Subject: [PATCH 13/13] #175 add UnitTest(@next2d/text) --- .../TextAreaMovePositionService.test.ts | 31 ++++++++++++ .../TextAreaRegisterEventUseCase.test.ts | 50 +++++++++++++++++++ ...TextFormatGenerateFontStyleService.test.ts | 2 +- .../TextFormatGetWidthMarginService.test.ts | 2 +- ...FormatHtmlTextGenerateStyleService.test.ts | 2 +- .../service/TextFormatIsSameService.test.ts | 2 +- .../TextFormatSetDefaultService.test.ts | 2 +- .../TextParserAdjustmentHeightService.test.ts | 2 +- .../TextParserParseStyleService.test.ts | 2 +- 9 files changed, 88 insertions(+), 7 deletions(-) create mode 100644 packages/text/src/TextArea/service/TextAreaMovePositionService.test.ts create mode 100644 packages/text/src/TextArea/usecase/TextAreaRegisterEventUseCase.test.ts diff --git a/packages/text/src/TextArea/service/TextAreaMovePositionService.test.ts b/packages/text/src/TextArea/service/TextAreaMovePositionService.test.ts new file mode 100644 index 00000000..fd07d427 --- /dev/null +++ b/packages/text/src/TextArea/service/TextAreaMovePositionService.test.ts @@ -0,0 +1,31 @@ +import type { TextField } from "../../TextField"; +import { execute } from "./TextAreaMovePositionService"; +import { describe, expect, it } from "vitest"; +import { + $textArea, +} from "../../TextUtil"; + +describe("TextAreaMovePositionService.js Test", () => +{ + it("test case", () => + { + // Arrange + const textField = { + localToGlobal: () => ({ x: 20, y: 30 }), + $textData: { + textTable: [ + { line: 0, mode: "break", w: 10 }, + { line: 1, mode: "normal", w: 20 }, + ], + heightTable: [10, 20], + } + } as unknown as TextField; + + // Act + execute(textField); + + // Assert + expect($textArea.style.left).toBe("20px"); + expect($textArea.style.top).toBe("30px"); + }); +}); \ No newline at end of file diff --git a/packages/text/src/TextArea/usecase/TextAreaRegisterEventUseCase.test.ts b/packages/text/src/TextArea/usecase/TextAreaRegisterEventUseCase.test.ts new file mode 100644 index 00000000..3a3b2682 --- /dev/null +++ b/packages/text/src/TextArea/usecase/TextAreaRegisterEventUseCase.test.ts @@ -0,0 +1,50 @@ +import { execute } from "./TextAreaRegisterEventUseCase"; +import { describe, expect, it, vi } from "vitest"; + +describe("TextAreaRegisterEventUseCase Test", () => +{ + it("test case", () => + { + const textArea = document.createElement("textarea"); + + let compositionstart = false; + let compositionupdate = false; + let compositionend = false; + let input = false; + textArea.addEventListener = vi.fn((type) => + { + switch (type) { + case "compositionstart": + compositionstart = true; + break; + + case "compositionupdate": + compositionupdate = true; + break; + + case "compositionend": + compositionend = true; + break; + + case "input": + input = true; + break; + + default: + break; + } + }); + + expect(compositionstart).toBe(false); + expect(compositionupdate).toBe(false); + expect(compositionend).toBe(false); + expect(input).toBe(false); + + execute(textArea); + + expect(compositionstart).toBe(true); + expect(compositionupdate).toBe(true); + expect(compositionend).toBe(true); + expect(input).toBe(true); + }); +}); \ No newline at end of file diff --git a/packages/text/src/TextFormat/service/TextFormatGenerateFontStyleService.test.ts b/packages/text/src/TextFormat/service/TextFormatGenerateFontStyleService.test.ts index dfbc465d..700c272b 100644 --- a/packages/text/src/TextFormat/service/TextFormatGenerateFontStyleService.test.ts +++ b/packages/text/src/TextFormat/service/TextFormatGenerateFontStyleService.test.ts @@ -2,7 +2,7 @@ import { execute } from "./TextFormatGenerateFontStyleService"; import { TextFormat } from "../../TextFormat"; import { describe, expect, it } from "vitest"; -describe("TextFormatGenerateFontStyleService.js length test", () => +describe("TextFormatGenerateFontStyleService.js test", () => { it("test case1", () => { diff --git a/packages/text/src/TextFormat/service/TextFormatGetWidthMarginService.test.ts b/packages/text/src/TextFormat/service/TextFormatGetWidthMarginService.test.ts index 9d4b1f67..bb9b212d 100644 --- a/packages/text/src/TextFormat/service/TextFormatGetWidthMarginService.test.ts +++ b/packages/text/src/TextFormat/service/TextFormatGetWidthMarginService.test.ts @@ -2,7 +2,7 @@ import { execute } from "./TextFormatGetWidthMarginService"; import { TextFormat } from "../../TextFormat"; import { describe, expect, it } from "vitest"; -describe("TextFormatGetWidthMarginService.js length test", () => +describe("TextFormatGetWidthMarginService.js test", () => { it("test case1", () => { diff --git a/packages/text/src/TextFormat/service/TextFormatHtmlTextGenerateStyleService.test.ts b/packages/text/src/TextFormat/service/TextFormatHtmlTextGenerateStyleService.test.ts index 37ed4465..a21e9e9c 100644 --- a/packages/text/src/TextFormat/service/TextFormatHtmlTextGenerateStyleService.test.ts +++ b/packages/text/src/TextFormat/service/TextFormatHtmlTextGenerateStyleService.test.ts @@ -3,7 +3,7 @@ import { execute as textFormatSetDefaultService } from "./TextFormatSetDefaultSe import { TextFormat } from "../../TextFormat"; import { describe, expect, it } from "vitest"; -describe("TextFormatHtmlTextGenerateStyleService.js length test", () => +describe("TextFormatHtmlTextGenerateStyleService.js test", () => { it("test case1", () => { diff --git a/packages/text/src/TextFormat/service/TextFormatIsSameService.test.ts b/packages/text/src/TextFormat/service/TextFormatIsSameService.test.ts index 1e8ebc0c..a8e808df 100644 --- a/packages/text/src/TextFormat/service/TextFormatIsSameService.test.ts +++ b/packages/text/src/TextFormat/service/TextFormatIsSameService.test.ts @@ -2,7 +2,7 @@ import { execute } from "./TextFormatIsSameService"; import { TextFormat } from "../../TextFormat"; import { describe, expect, it } from "vitest"; -describe("TextFormatIsSameService.js length test", () => +describe("TextFormatIsSameService.js test", () => { it("test case1", () => { diff --git a/packages/text/src/TextFormat/service/TextFormatSetDefaultService.test.ts b/packages/text/src/TextFormat/service/TextFormatSetDefaultService.test.ts index 70f2ac89..0b7d07ee 100644 --- a/packages/text/src/TextFormat/service/TextFormatSetDefaultService.test.ts +++ b/packages/text/src/TextFormat/service/TextFormatSetDefaultService.test.ts @@ -2,7 +2,7 @@ import { execute } from "./TextFormatSetDefaultService"; import { TextFormat } from "../../TextFormat"; import { describe, expect, it } from "vitest"; -describe("TextFormatSetDefaultService.js length test", () => +describe("TextFormatSetDefaultService.js test", () => { it("default test case1", () => { diff --git a/packages/text/src/TextParser/service/TextParserAdjustmentHeightService.test.ts b/packages/text/src/TextParser/service/TextParserAdjustmentHeightService.test.ts index f6a3b728..7de9a1c7 100644 --- a/packages/text/src/TextParser/service/TextParserAdjustmentHeightService.test.ts +++ b/packages/text/src/TextParser/service/TextParserAdjustmentHeightService.test.ts @@ -3,7 +3,7 @@ import { TextData } from "../../TextData"; import { describe, expect, it } from "vitest"; import { ITextObject } from "../../interface/ITextObject"; -describe("TextParserAdjustmentHeightService.js length test", () => +describe("TextParserAdjustmentHeightService.js Test", () => { it("test case1", () => { diff --git a/packages/text/src/TextParser/service/TextParserParseStyleService.test.ts b/packages/text/src/TextParser/service/TextParserParseStyleService.test.ts index 55029cd5..d8ed4b27 100644 --- a/packages/text/src/TextParser/service/TextParserParseStyleService.test.ts +++ b/packages/text/src/TextParser/service/TextParserParseStyleService.test.ts @@ -1,7 +1,7 @@ import { execute } from "./TextParserParseStyleService"; import { describe, expect, it } from "vitest"; -describe("TextParserParseStyleService.js length test", () => +describe("TextParserParseStyleService.js Test", () => { it("test case1", () => {