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?",
]);
});
});