import * as React from "react"; import { render, screen } from "@testing-library/react"; import { clearMultilineCache, splitMultilineText } from "../src/multi-line"; import Breaker from "linebreak"; // 1 char === 1 px according to the testing library. This is not realistic but nice for testing. const longStr = "This is a quite long string that will need to wrap at least a couple times in order to fit on the screen. Who knows how many times?"; const newlineStr = "This is a quite long string \nthat will need to wrap at least a \ncouple times in order to \nfit on the screen. Who knows how many times?"; describe("multi-line-layout", () => { beforeEach(() => { clearMultilineCache(); CanvasRenderingContext2D.prototype.measureText = jest.fn((str: string) => { let width = 0; for (const char of str) { // eslint-disable-next-line unicorn/prefer-code-point width += char.charCodeAt(0) / 12; } return { width, actualBoundingBoxAscent: 1, actualBoundingBoxDescent: 1, actualBoundingBoxLeft: 1, actualBoundingBoxRight: width, fontBoundingBoxAscent: 1, fontBoundingBoxDescent: 1, }; }); }); test("short-sentence", () => { render(); const canvas = screen.getByTestId("canvas") as HTMLCanvasElement; const ctx = canvas.getContext("2d", { alpha: false, }); expect(ctx).not.toBeNull(); if (ctx === null) { throw new Error("Error"); } const spanned = splitMultilineText(ctx, "Test this short string", "12px bold", 400, false); expect(spanned[0]).toEqual("Test this short string"); }); test("long-sentence", () => { render(); const canvas = screen.getByTestId("canvas") as HTMLCanvasElement; const ctx = canvas.getContext("2d", { alpha: false, }); expect(ctx).not.toBeNull(); if (ctx === null) { throw new Error("Error"); } const spanned = splitMultilineText(ctx, longStr, "12px bold", 400, false); expect(spanned).toEqual([ "This is a quite long string that will need to wrap", "at least a couple times in order to fit on the", "screen. Who knows how many times?", ]); }); test("dash-sentence", () => { render(); const canvas = screen.getByTestId("canvas") as HTMLCanvasElement; const ctx = canvas.getContext("2d", { alpha: false, }); expect(ctx).not.toBeNull(); if (ctx === null) { throw new Error("Error"); } const spanned = splitMultilineText(ctx, longStr.split(" ").join("-"), "12px bold", 400, false, s => { const r: number[] = []; const b = new Breaker(s); let br = b.nextBreak(); while (br !== null) { r.push(br.position); br = b.nextBreak(); } return r; }); expect(spanned).toEqual([ "This-is-a-quite-long-string-that-will-need-to-", "wrap-at-least-a-couple-times-in-order-to-fit-on-", "the-screen.-Who-knows-how-many-times?", ]); }); test("zero width", () => { render(); ``; const canvas = screen.getByTestId("canvas") as HTMLCanvasElement; const ctx = canvas.getContext("2d", { alpha: false, }); expect(ctx).not.toBeNull(); if (ctx === null) { throw new Error("Error"); } const spanned = splitMultilineText(ctx, newlineStr, "12px bold", 0, false); expect(spanned).toEqual([]); }); test("newlines", () => { render(); ``; const canvas = screen.getByTestId("canvas") as HTMLCanvasElement; const ctx = canvas.getContext("2d", { alpha: false, }); expect(ctx).not.toBeNull(); if (ctx === null) { throw new Error("Error"); } const spanned = splitMultilineText(ctx, newlineStr, "12px bold", 400, false); expect(spanned).toEqual([ "This is a quite long string", "that will need to wrap at least a", "couple times in order to", "fit on the screen. Who knows how many times?", ]); }); test("hyperwrap", () => { render(); const canvas = screen.getByTestId("canvas") as HTMLCanvasElement; const ctx = canvas.getContext("2d", { alpha: false, }); expect(ctx).not.toBeNull(); if (ctx === null) { throw new Error("Error"); } for (let i = 0; i < 1_000_000; i++) { splitMultilineText(ctx, longStr + i, "12px bold", 400, true); } const spanned = splitMultilineText(ctx, longStr, "12px bold", 400, true); expect(spanned).toEqual([ "This is a quite long string that will need to wrap", "at least a couple times in order to fit on the", "screen. Who knows how many times?", ]); }); });