diff --git a/package-lock.json b/package-lock.json index 056844ab..838e44cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@next2d/player", - "version": "2.6.2", + "version": "2.9.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@next2d/player", - "version": "2.6.2", + "version": "2.9.0", "license": "MIT", "workspaces": [ "packages/*" @@ -25,7 +25,7 @@ "@types/node": "^24.10.1", "@typescript-eslint/eslint-plugin": "^8.46.4", "@typescript-eslint/parser": "^8.46.4", - "@vitest/web-worker": "^4.0.8", + "@vitest/web-worker": "^4.0.9", "eslint": "^9.39.1", "eslint-plugin-unused-imports": "^4.3.0", "globals": "^16.5.0", @@ -34,7 +34,7 @@ "tslib": "^2.8.1", "typescript": "^5.9.3", "vite": "^7.2.2", - "vitest": "^4.0.8", + "vitest": "^4.0.9", "vitest-webgl-canvas-mock": "^1.1.0", "xml2js": "^0.6.2" }, @@ -1783,16 +1783,16 @@ } }, "node_modules/@vitest/expect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.8.tgz", - "integrity": "sha512-Rv0eabdP/xjAHQGr8cjBm+NnLHNoL268lMDK85w2aAGLFoVKLd8QGnVon5lLtkXQCoYaNL0wg04EGnyKkkKhPA==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.9.tgz", + "integrity": "sha512-C2vyXf5/Jfj1vl4DQYxjib3jzyuswMi/KHHVN2z+H4v16hdJ7jMZ0OGe3uOVIt6LyJsAofDdaJNIFEpQcrSTFw==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.8", - "@vitest/utils": "4.0.8", + "@vitest/spy": "4.0.9", + "@vitest/utils": "4.0.9", "chai": "^6.2.0", "tinyrainbow": "^3.0.3" }, @@ -1801,13 +1801,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.8.tgz", - "integrity": "sha512-9FRM3MZCedXH3+pIh+ME5Up2NBBHDq0wqwhOKkN4VnvCiKbVxddqH9mSGPZeawjd12pCOGnl+lo/ZGHt0/dQSg==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.9.tgz", + "integrity": "sha512-PUyaowQFHW+9FKb4dsvvBM4o025rWMlEDXdWRxIOilGaHREYTi5Q2Rt9VCgXgPy/hHZu1LeuXtrA/GdzOatP2g==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.0.8", + "@vitest/spy": "4.0.9", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -1838,9 +1838,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.8.tgz", - "integrity": "sha512-qRrjdRkINi9DaZHAimV+8ia9Gq6LeGz2CgIEmMLz3sBDYV53EsnLZbJMR1q84z1HZCMsf7s0orDgZn7ScXsZKg==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.9.tgz", + "integrity": "sha512-Hor0IBTwEi/uZqB7pvGepyElaM8J75pYjrrqbC8ZYMB9/4n5QA63KC15xhT+sqHpdGWfdnPo96E8lQUxs2YzSQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1851,13 +1851,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.8.tgz", - "integrity": "sha512-mdY8Sf1gsM8hKJUQfiPT3pn1n8RF4QBcJYFslgWh41JTfrK1cbqY8whpGCFzBl45LN028g0njLCYm0d7XxSaQQ==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.9.tgz", + "integrity": "sha512-aF77tsXdEvIJRkj9uJZnHtovsVIx22Ambft9HudC+XuG/on1NY/bf5dlDti1N35eJT+QZLb4RF/5dTIG18s98w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.8", + "@vitest/utils": "4.0.9", "pathe": "^2.0.3" }, "funding": { @@ -1865,13 +1865,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.8.tgz", - "integrity": "sha512-Nar9OTU03KGiubrIOFhcfHg8FYaRaNT+bh5VUlNz8stFhCZPNrJvmZkhsr1jtaYvuefYFwK2Hwrq026u4uPWCw==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.9.tgz", + "integrity": "sha512-r1qR4oYstPbnOjg0Vgd3E8ADJbi4ditCzqr+Z9foUrRhIy778BleNyZMeAJ2EjV+r4ASAaDsdciC9ryMy8xMMg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.8", + "@vitest/pretty-format": "4.0.9", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -1880,9 +1880,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.8.tgz", - "integrity": "sha512-nvGVqUunyCgZH7kmo+Ord4WgZ7lN0sOULYXUOYuHr55dvg9YvMz3izfB189Pgp28w0vWFbEEfNc/c3VTrqrXeA==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.9.tgz", + "integrity": "sha512-J9Ttsq0hDXmxmT8CUOWUr1cqqAj2FJRGTdyEjSR+NjoOGKEqkEWj+09yC0HhI8t1W6t4Ctqawl1onHgipJve1A==", "dev": true, "license": "MIT", "funding": { @@ -1890,13 +1890,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.8.tgz", - "integrity": "sha512-pdk2phO5NDvEFfUTxcTP8RFYjVj/kfLSPIN5ebP2Mu9kcIMeAQTbknqcFEyBcC4z2pJlJI9aS5UQjcYfhmKAow==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.9.tgz", + "integrity": "sha512-cEol6ygTzY4rUPvNZM19sDf7zGa35IYTm9wfzkHoT/f5jX10IOY7QleWSOh5T0e3I3WVozwK5Asom79qW8DiuQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.8", + "@vitest/pretty-format": "4.0.9", "tinyrainbow": "^3.0.3" }, "funding": { @@ -1904,9 +1904,9 @@ } }, "node_modules/@vitest/web-worker": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@vitest/web-worker/-/web-worker-4.0.8.tgz", - "integrity": "sha512-Dt+vm2EJd/03RDA4jpbUMy2M8cv5SBA7aD3uUTP2eGzVxabfwUhWHFaWYhHiq4QdjDAU12Ztdek4e2u8LftKNw==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@vitest/web-worker/-/web-worker-4.0.9.tgz", + "integrity": "sha512-rAX5p1S1ZE9ZAzTDkk7N0l1L0y5V5QLc/xKXwhS2X/GuIdDxrJQHXsmY65HR51x9p3LU0OgaeZu+x1rh1dLP+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1916,7 +1916,7 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "4.0.8" + "vitest": "4.0.9" } }, "node_modules/acorn": { @@ -3012,9 +3012,9 @@ "license": "ISC" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -4049,20 +4049,20 @@ } }, "node_modules/vitest": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.8.tgz", - "integrity": "sha512-urzu3NCEV0Qa0Y2PwvBtRgmNtxhj5t5ULw7cuKhIHh3OrkKTLlut0lnBOv9qe5OvbkMH2g38G7KPDCTpIytBVg==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.9.tgz", + "integrity": "sha512-E0Ja2AX4th+CG33yAFRC+d1wFx2pzU5r6HtG6LiPSE04flaE0qB6YyjSw9ZcpJAtVPfsvZGtJlKWZpuW7EHRxg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vitest/expect": "4.0.8", - "@vitest/mocker": "4.0.8", - "@vitest/pretty-format": "4.0.8", - "@vitest/runner": "4.0.8", - "@vitest/snapshot": "4.0.8", - "@vitest/spy": "4.0.8", - "@vitest/utils": "4.0.8", + "@vitest/expect": "4.0.9", + "@vitest/mocker": "4.0.9", + "@vitest/pretty-format": "4.0.9", + "@vitest/runner": "4.0.9", + "@vitest/snapshot": "4.0.9", + "@vitest/spy": "4.0.9", + "@vitest/utils": "4.0.9", "debug": "^4.4.3", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", @@ -4090,10 +4090,10 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.8", - "@vitest/browser-preview": "4.0.8", - "@vitest/browser-webdriverio": "4.0.8", - "@vitest/ui": "4.0.8", + "@vitest/browser-playwright": "4.0.9", + "@vitest/browser-preview": "4.0.9", + "@vitest/browser-webdriverio": "4.0.9", + "@vitest/ui": "4.0.9", "happy-dom": "*", "jsdom": "*" }, diff --git a/package.json b/package.json index 2a6e1ea7..fa830c84 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@next2d/player", - "version": "2.8.0", + "version": "2.9.0", "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", @@ -54,7 +54,7 @@ "@types/node": "^24.10.1", "@typescript-eslint/eslint-plugin": "^8.46.4", "@typescript-eslint/parser": "^8.46.4", - "@vitest/web-worker": "^4.0.8", + "@vitest/web-worker": "^4.0.9", "eslint": "^9.39.1", "eslint-plugin-unused-imports": "^4.3.0", "globals": "^16.5.0", @@ -63,7 +63,7 @@ "tslib": "^2.8.1", "typescript": "^5.9.3", "vite": "^7.2.2", - "vitest": "^4.0.8", + "vitest": "^4.0.9", "vitest-webgl-canvas-mock": "^1.1.0", "xml2js": "^0.6.2" }, diff --git a/packages/renderer/src/Command/usecase/CommandCaptureUseCase.test.ts b/packages/renderer/src/Command/usecase/CommandCaptureUseCase.test.ts new file mode 100644 index 00000000..9c5d46ce --- /dev/null +++ b/packages/renderer/src/Command/usecase/CommandCaptureUseCase.test.ts @@ -0,0 +1,249 @@ +import { describe, expect, it, vi, beforeEach } from "vitest"; + +vi.mock("../../RendererUtil", () => ({ + $context: { + clearTransferBounds: vi.fn(), + reset: vi.fn(), + setTransform: vi.fn(), + updateBackgroundColor: vi.fn(), + fillBackgroundColor: vi.fn(), + drawArraysInstanced: vi.fn(), + createImageBitmap: vi.fn() + } +})); + +vi.mock("../../DisplayObjectContainer/usecase/DisplayObjectContainerRenderUseCase", () => ({ + execute: vi.fn((queue, index) => index) +})); + +vi.mock("../../Shape/usecase/ShapeRenderUseCase", () => ({ + execute: vi.fn((queue, index) => index) +})); + +vi.mock("../../TextField/usecase/TextFieldRenderUseCase", () => ({ + execute: vi.fn((queue, index) => index) +})); + +vi.mock("../../Video/usecase/VideoRenderUseCase", () => ({ + execute: vi.fn((queue, index) => index) +})); + +import { execute } from "./CommandCaptureUseCase"; +import { $context } from "../../RendererUtil"; + +describe("CommandCaptureUseCase.js test", () => +{ + beforeEach(() => + { + vi.clearAllMocks(); + ($context.createImageBitmap as any).mockResolvedValue({} as any); + }); + + it("execute test case1 - renders empty queue with default background", async () => + { + const renderQueue = new Float32Array([0]); + const width = 640; + const height = 480; + + await execute(renderQueue, width, height); + + expect($context.clearTransferBounds).toHaveBeenCalled(); + expect($context.reset).toHaveBeenCalled(); + expect($context.setTransform).toHaveBeenCalledWith(1, 0, 0, 1, 0, 0); + expect($context.updateBackgroundColor).toHaveBeenCalledWith(0, 0, 0, 0); + expect($context.fillBackgroundColor).toHaveBeenCalled(); + expect($context.drawArraysInstanced).toHaveBeenCalled(); + expect($context.createImageBitmap).toHaveBeenCalledWith(width, height); + }); + + it("execute test case2 - handles custom background color", async () => + { + const renderQueue = new Float32Array([0]); + const width = 640; + const height = 480; + const bgColor = 0xFF0000; + const bgAlpha = 1.0; + + await execute(renderQueue, width, height, bgColor, bgAlpha); + + expect($context.updateBackgroundColor).toHaveBeenCalledWith(1, 0, 0, bgAlpha); + }); + + it("execute test case3 - handles custom background color with alpha", async () => + { + const renderQueue = new Float32Array([0]); + const width = 640; + const height = 480; + const bgColor = 0x00FF00; + const bgAlpha = 0.5; + + await execute(renderQueue, width, height, bgColor, bgAlpha); + + expect($context.updateBackgroundColor).toHaveBeenCalledWith(0, 1, 0, bgAlpha); + }); + + it("execute test case4 - handles blue background color", async () => + { + const renderQueue = new Float32Array([0]); + const width = 640; + const height = 480; + const bgColor = 0x0000FF; + const bgAlpha = 1.0; + + await execute(renderQueue, width, height, bgColor, bgAlpha); + + expect($context.updateBackgroundColor).toHaveBeenCalledWith(0, 0, 1, bgAlpha); + }); + + it("execute test case5 - handles white background color", async () => + { + const renderQueue = new Float32Array([0]); + const width = 640; + const height = 480; + const bgColor = 0xFFFFFF; + const bgAlpha = 1.0; + + await execute(renderQueue, width, height, bgColor, bgAlpha); + + expect($context.updateBackgroundColor).toHaveBeenCalledWith(1, 1, 1, bgAlpha); + }); + + it("execute test case6 - processes queue with hidden object", async () => + { + const renderQueue = new Float32Array([0, 0, 0x01]); + const width = 640; + const height = 480; + + await execute(renderQueue, width, height); + + expect($context.clearTransferBounds).toHaveBeenCalled(); + expect($context.drawArraysInstanced).toHaveBeenCalled(); + }); + + it("execute test case7 - handles different canvas sizes", async () => + { + const renderQueue = new Float32Array([0]); + const width = 1920; + const height = 1080; + + await execute(renderQueue, width, height); + + expect($context.createImageBitmap).toHaveBeenCalledWith(width, height); + }); + + it("execute test case8 - handles small canvas sizes", async () => + { + const renderQueue = new Float32Array([0]); + const width = 100; + const height = 100; + + await execute(renderQueue, width, height); + + expect($context.createImageBitmap).toHaveBeenCalledWith(width, height); + }); + + it("execute test case9 - handles zero alpha background", async () => + { + const renderQueue = new Float32Array([0]); + const width = 640; + const height = 480; + const bgColor = 0xFF0000; + const bgAlpha = 0; + + await execute(renderQueue, width, height, bgColor, bgAlpha); + + expect($context.updateBackgroundColor).toHaveBeenCalledWith(1, 0, 0, 0); + }); + + it("execute test case10 - validates return type is Promise", async () => + { + const renderQueue = new Float32Array([0]); + const width = 640; + const height = 480; + + const result = execute(renderQueue, width, height); + + expect(result).toBeInstanceOf(Promise); + await result; + }); + + it("execute test case11 - handles null image bitmaps", async () => + { + const renderQueue = new Float32Array([0]); + const width = 640; + const height = 480; + const imageBitmaps = null; + + await execute(renderQueue, width, height, 0x000000, 0, imageBitmaps); + + expect($context.createImageBitmap).toHaveBeenCalledWith(width, height); + }); + + it("execute test case12 - handles empty image bitmaps array", async () => + { + const renderQueue = new Float32Array([0]); + const width = 640; + const height = 480; + const imageBitmaps: ImageBitmap[] = []; + + await execute(renderQueue, width, height, 0x000000, 0, imageBitmaps); + + expect($context.createImageBitmap).toHaveBeenCalledWith(width, height); + }); + + it("execute test case13 - handles partial transparency", async () => + { + const renderQueue = new Float32Array([0]); + const width = 640; + const height = 480; + const bgColor = 0x808080; + const bgAlpha = 0.75; + + await execute(renderQueue, width, height, bgColor, bgAlpha); + + const expectedR = (0x80) / 255; + const expectedG = (0x80) / 255; + const expectedB = (0x80) / 255; + + expect($context.updateBackgroundColor).toHaveBeenCalledWith( + expect.closeTo(expectedR, 2), + expect.closeTo(expectedG, 2), + expect.closeTo(expectedB, 2), + bgAlpha + ); + }); + + it("execute test case14 - validates context method call order", async () => + { + const renderQueue = new Float32Array([0]); + const width = 640; + const height = 480; + + await execute(renderQueue, width, height); + + const clearCall = $context.clearTransferBounds.mock.invocationCallOrder[0]; + const resetCall = $context.reset.mock.invocationCallOrder[0]; + const transformCall = $context.setTransform.mock.invocationCallOrder[0]; + const fillCall = $context.fillBackgroundColor.mock.invocationCallOrder[0]; + const drawCall = $context.drawArraysInstanced.mock.invocationCallOrder[0]; + + expect(clearCall).toBeLessThan(resetCall); + expect(resetCall).toBeLessThan(transformCall); + expect(transformCall).toBeLessThan(fillCall); + expect(fillCall).toBeLessThan(drawCall); + }); + + it("execute test case15 - handles large render queue", async () => + { + const renderQueue = new Float32Array(1000); + renderQueue[0] = 0; + const width = 640; + const height = 480; + + await execute(renderQueue, width, height); + + expect($context.clearTransferBounds).toHaveBeenCalled(); + expect($context.drawArraysInstanced).toHaveBeenCalled(); + }); +}); + diff --git a/packages/renderer/src/Command/usecase/CommandCaptureUseCase.ts b/packages/renderer/src/Command/usecase/CommandCaptureUseCase.ts index 1998fbd2..29d9fd17 100644 --- a/packages/renderer/src/Command/usecase/CommandCaptureUseCase.ts +++ b/packages/renderer/src/Command/usecase/CommandCaptureUseCase.ts @@ -36,9 +36,9 @@ export const execute = async ( $context.reset(); $context.setTransform(1, 0, 0, 1, 0, 0); $context.updateBackgroundColor( - bg_color >> 16 & 0xff / 255, - bg_color >> 8 & 0xff / 255, - bg_color & 0xff / 255, + (bg_color >> 16 & 0xff) / 255, + (bg_color >> 8 & 0xff) / 255, + (bg_color & 0xff) / 255, bg_alpha ); $context.fillBackgroundColor(); diff --git a/packages/renderer/src/Command/usecase/CommandRenderUseCase.test.ts b/packages/renderer/src/Command/usecase/CommandRenderUseCase.test.ts new file mode 100644 index 00000000..2ac4b7ba --- /dev/null +++ b/packages/renderer/src/Command/usecase/CommandRenderUseCase.test.ts @@ -0,0 +1,239 @@ +import { describe, expect, it, vi, beforeEach } from "vitest"; + +let mockIsResize = false; + +vi.mock("../../RendererUtil", () => ({ + $context: { + clearTransferBounds: vi.fn(), + reset: vi.fn(), + setTransform: vi.fn(), + updateBackgroundColor: vi.fn(), + fillBackgroundColor: vi.fn(), + drawArraysInstanced: vi.fn(), + transferMainCanvas: vi.fn() + }, + $isResize: () => mockIsResize, + $resizeComplete: vi.fn() +})); + +vi.mock("../../DisplayObjectContainer/usecase/DisplayObjectContainerRenderUseCase", () => ({ + execute: vi.fn((queue, index) => index) +})); + +vi.mock("../../Shape/usecase/ShapeRenderUseCase", () => ({ + execute: vi.fn((queue, index) => index) +})); + +vi.mock("../../TextField/usecase/TextFieldRenderUseCase", () => ({ + execute: vi.fn((queue, index) => index) +})); + +vi.mock("../../Video/usecase/VideoRenderUseCase", () => ({ + execute: vi.fn((queue, index) => index) +})); + +import { execute } from "./CommandRenderUseCase"; +import { $context, $resizeComplete } from "../../RendererUtil"; + +describe("CommandRenderUseCase.js test", () => +{ + beforeEach(() => + { + vi.clearAllMocks(); + mockIsResize = false; + }); + + it("execute test case1 - renders with default background color (-1)", () => + { + const renderQueue = new Float32Array([-1]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + expect($context.clearTransferBounds).toHaveBeenCalled(); + expect($context.reset).toHaveBeenCalled(); + expect($context.setTransform).toHaveBeenCalledWith(1, 0, 0, 1, 0, 0); + expect($context.fillBackgroundColor).toHaveBeenCalled(); + expect($context.drawArraysInstanced).toHaveBeenCalled(); + expect($context.transferMainCanvas).toHaveBeenCalled(); + }); + + it("execute test case2 - renders with red background color", () => + { + const renderQueue = new Float32Array([0xFF0000]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + expect($context.updateBackgroundColor).toHaveBeenCalledWith(1, 0, 0, 1); + }); + + it("execute test case3 - renders with green background color", () => + { + const renderQueue = new Float32Array([0x00FF00]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + expect($context.updateBackgroundColor).toHaveBeenCalledWith(0, 1, 0, 1); + }); + + it("execute test case4 - renders with blue background color", () => + { + const renderQueue = new Float32Array([0x0000FF]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + expect($context.updateBackgroundColor).toHaveBeenCalledWith(0, 0, 1, 1); + }); + + it("execute test case5 - renders with white background color", () => + { + const renderQueue = new Float32Array([0xFFFFFF]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + expect($context.updateBackgroundColor).toHaveBeenCalledWith(1, 1, 1, 1); + }); + + it("execute test case6 - handles resize flag true", () => + { + mockIsResize = true; + + const renderQueue = new Float32Array([-1]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + expect($resizeComplete).toHaveBeenCalled(); + }); + + it("execute test case7 - handles resize flag false", () => + { + mockIsResize = false; + + const renderQueue = new Float32Array([-1]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + expect($resizeComplete).not.toHaveBeenCalled(); + }); + + it("execute test case8 - skips hidden objects", () => + { + const renderQueue = new Float32Array([-1, 0, 0x01]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + expect($context.drawArraysInstanced).toHaveBeenCalled(); + }); + + it("execute test case9 - handles null image bitmaps", () => + { + const renderQueue = new Float32Array([-1]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + expect($context.transferMainCanvas).toHaveBeenCalled(); + }); + + it("execute test case10 - handles empty image bitmaps array", () => + { + const renderQueue = new Float32Array([-1]); + const imageBitmaps: ImageBitmap[] = []; + + execute(renderQueue, imageBitmaps); + + expect($context.transferMainCanvas).toHaveBeenCalled(); + }); + + it("execute test case11 - validates context method call order", () => + { + const renderQueue = new Float32Array([-1]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + const clearCall = $context.clearTransferBounds.mock.invocationCallOrder[0]; + const resetCall = $context.reset.mock.invocationCallOrder[0]; + const transformCall = $context.setTransform.mock.invocationCallOrder[0]; + const fillCall = $context.fillBackgroundColor.mock.invocationCallOrder[0]; + const drawCall = $context.drawArraysInstanced.mock.invocationCallOrder[0]; + const transferCall = $context.transferMainCanvas.mock.invocationCallOrder[0]; + + expect(clearCall).toBeLessThan(resetCall); + expect(resetCall).toBeLessThan(transformCall); + expect(transformCall).toBeLessThan(fillCall); + expect(fillCall).toBeLessThan(drawCall); + expect(drawCall).toBeLessThan(transferCall); + }); + + it("execute test case12 - handles gray background color", () => + { + const renderQueue = new Float32Array([0x808080]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + const expectedR = (0x80) / 255; + const expectedG = (0x80) / 255; + const expectedB = (0x80) / 255; + + expect($context.updateBackgroundColor).toHaveBeenCalledWith( + expect.closeTo(expectedR, 2), + expect.closeTo(expectedG, 2), + expect.closeTo(expectedB, 2), + 1 + ); + }); + + it("execute test case13 - handles black background color (0x000000)", () => + { + const renderQueue = new Float32Array([0x000000]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + expect($context.updateBackgroundColor).toHaveBeenCalledWith(0, 0, 0, 1); + }); + + it("execute test case14 - handles empty render queue", () => + { + const renderQueue = new Float32Array([-1]); + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + expect($context.clearTransferBounds).toHaveBeenCalled(); + expect($context.transferMainCanvas).toHaveBeenCalled(); + }); + + it("execute test case15 - handles large render queue", () => + { + const renderQueue = new Float32Array(1000); + renderQueue[0] = -1; + const imageBitmaps = null; + + execute(renderQueue, imageBitmaps); + + expect($context.clearTransferBounds).toHaveBeenCalled(); + expect($context.drawArraysInstanced).toHaveBeenCalled(); + expect($context.transferMainCanvas).toHaveBeenCalled(); + }); + + it("execute test case16 - validates return type is void", () => + { + const renderQueue = new Float32Array([-1]); + const imageBitmaps = null; + + const result = execute(renderQueue, imageBitmaps); + + expect(result).toBeUndefined(); + }); +}); + diff --git a/packages/renderer/src/Command/usecase/CommandRenderUseCase.ts b/packages/renderer/src/Command/usecase/CommandRenderUseCase.ts index cdea2fe9..b8fd26aa 100644 --- a/packages/renderer/src/Command/usecase/CommandRenderUseCase.ts +++ b/packages/renderer/src/Command/usecase/CommandRenderUseCase.ts @@ -42,9 +42,9 @@ export const execute = ( $context.updateBackgroundColor(0, 0, 0, 0); } else { $context.updateBackgroundColor( - $color >> 16 & 0xff / 255, - $color >> 8 & 0xff / 255, - $color & 0xff / 255, + ($color >> 16 & 0xff) / 255, + ($color >> 8 & 0xff) / 255, + ($color & 0xff) / 255, 1 ); } diff --git a/src/index.ts b/src/index.ts index 4e50c90e..1ddb4ead 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.8.0 %c https://next2d.app", + console.log("%c Next2D Player %c 2.9.0 %c https://next2d.app", "color: #fff; background: #5f5f5f", "color: #fff; background: #4bc729", "");