Add QWord table structure commands

This commit is contained in:
Курнат Андрей
2026-06-02 09:01:20 +03:00
parent 26bf4b5873
commit a9f9aa6cca
3 changed files with 363 additions and 5 deletions
+126
View File
@@ -1,4 +1,5 @@
import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
import { useState } from "react";
import { afterEach, describe, expect, it } from "vitest";
import { vi } from "vitest";
import type { WordDocument } from "../../types";
@@ -141,6 +142,131 @@ describe("QWord", () => {
}
});
it("сохраняет активную ячейку после вставки таблицы и перерендера", () => {
const originalResizeObserver = globalThis.ResizeObserver;
const originalRequestAnimationFrame = window.requestAnimationFrame;
const onChange = vi.fn();
globalThis.ResizeObserver = class {
observe() {}
disconnect() {}
} as unknown as typeof ResizeObserver;
window.requestAnimationFrame = ((callback: FrameRequestCallback) => {
callback(0);
return 1;
}) as typeof window.requestAnimationFrame;
const document: WordDocument = {
id: "word-insert-table-restore-test",
title: "Активная таблица.docx",
updatedAt: "2026-06-02T00:00:00.000Z",
html: "<p>Перед таблицей</p>"
};
function StatefulQWord() {
const [currentDocument, setCurrentDocument] = useState(document);
return (
<QWord
document={currentDocument}
onChange={(nextDocument) => {
onChange(nextDocument);
setCurrentDocument(nextDocument);
}}
/>
);
}
try {
render(<StatefulQWord />);
fireEvent.click(screen.getByRole("tab", { name: "Вставка" }));
const tableButton = screen.getByRole("button", { name: "Таблица" });
expect(fireEvent.mouseDown(tableButton)).toBe(false);
fireEvent.click(tableButton);
const rowButton = screen.getByRole("button", { name: "Строка ниже" });
expect(fireEvent.mouseDown(rowButton)).toBe(false);
fireEvent.click(rowButton);
const updatedDocument = onChange.mock.calls[onChange.mock.calls.length - 1]?.[0] as WordDocument | undefined;
expect(updatedDocument?.html.match(/<tr/g)).toHaveLength(4);
expect(updatedDocument?.html.match(/<td/g)).toHaveLength(12);
} finally {
globalThis.ResizeObserver = originalResizeObserver;
window.requestAnimationFrame = originalRequestAnimationFrame;
}
});
it("добавляет строку и столбец к выбранной таблице", () => {
const originalResizeObserver = globalThis.ResizeObserver;
const originalRequestAnimationFrame = window.requestAnimationFrame;
const onChange = vi.fn();
globalThis.ResizeObserver = class {
observe() {}
disconnect() {}
} as unknown as typeof ResizeObserver;
window.requestAnimationFrame = ((callback: FrameRequestCallback) => {
callback(0);
return 1;
}) as typeof window.requestAnimationFrame;
const document: WordDocument = {
id: "word-table-structure-test",
title: "Структура таблицы.docx",
updatedAt: "2026-06-02T00:00:00.000Z",
html: "<table><tbody><tr><td>A</td><td>B</td></tr></tbody></table>"
};
function selectCell(text: string) {
const cell = screen.getByText(text).closest("td");
expect(cell).toBeInTheDocument();
const range = window.document.createRange();
range.selectNodeContents(cell as HTMLTableCellElement);
window.getSelection()?.removeAllRanges();
window.getSelection()?.addRange(range);
}
function StatefulQWord() {
const [currentDocument, setCurrentDocument] = useState(document);
return (
<QWord
document={currentDocument}
onChange={(nextDocument) => {
onChange(nextDocument);
setCurrentDocument(nextDocument);
}}
/>
);
}
try {
render(<StatefulQWord />);
fireEvent.click(screen.getByRole("tab", { name: "Вставка" }));
selectCell("A");
const rowButton = screen.getByRole("button", { name: "Строка ниже" });
expect(fireEvent.mouseDown(rowButton)).toBe(false);
fireEvent.click(rowButton);
let updatedDocument = onChange.mock.calls[onChange.mock.calls.length - 1]?.[0] as WordDocument | undefined;
expect(updatedDocument?.html.match(/<tr/g)).toHaveLength(2);
expect(updatedDocument?.html.match(/<td/g)).toHaveLength(4);
selectCell("A");
const columnButton = screen.getByRole("button", { name: "Столбец справа" });
expect(fireEvent.mouseDown(columnButton)).toBe(false);
fireEvent.click(columnButton);
updatedDocument = onChange.mock.calls[onChange.mock.calls.length - 1]?.[0] as WordDocument | undefined;
expect(updatedDocument?.html.match(/<tr/g)).toHaveLength(2);
expect(updatedDocument?.html.match(/<td/g)).toHaveLength(6);
} finally {
globalThis.ResizeObserver = originalResizeObserver;
window.requestAnimationFrame = originalRequestAnimationFrame;
}
});
it("обновляет текущую страницу в статусе при прокрутке документа", async () => {
const originalResizeObserver = globalThis.ResizeObserver;
const originalRequestAnimationFrame = window.requestAnimationFrame;