mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-06-11 16:34:57 +03:00
96 lines
4.2 KiB
JavaScript
96 lines
4.2 KiB
JavaScript
// web-test table/grid v1.20 — Form-grid operations: read table rows, fill rows, delete rows.
|
||
// Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||
//
|
||
// "Grid" в терминах 1С — таблица на форме (.gridLine/.gridBody/.grid в DOM):
|
||
// табличные части документов, формы списков, ТЧ настроек и т.п.
|
||
// Отдельно от SpreadsheetDocument (engine/spreadsheet/spreadsheet.mjs).
|
||
|
||
import { page, ensureConnected } from '../core/state.mjs';
|
||
import { detectFormScript, readTableScript, resolveGridScript } from '../../dom.mjs';
|
||
import { findDeleteRowCoordsScript, countGridRowsScript } from '../../dom/grid.mjs';
|
||
import { isInputFocusedInGrid } from '../core/helpers.mjs';
|
||
import { dismissPendingErrors } from '../core/errors.mjs';
|
||
import { waitForStable } from '../core/wait.mjs';
|
||
import { clickElement } from '../core/click.mjs';
|
||
import { returnFormState } from '../core/helpers.mjs';
|
||
|
||
/** Read structured table data with pagination. Returns columns, rows, total count. */
|
||
export async function readTable({ maxRows = 20, offset = 0, table } = {}) {
|
||
ensureConnected();
|
||
const formNum = await page.evaluate(detectFormScript());
|
||
if (formNum === null) throw new Error('readTable: no form found');
|
||
let gridSelector;
|
||
if (table) {
|
||
const resolved = await page.evaluate(resolveGridScript(formNum, table));
|
||
if (resolved.error) throw new Error(`readTable: ${resolved.message || resolved.error}. Available: ${resolved.available?.map(a => a.name).join(', ') || 'none'}`);
|
||
gridSelector = resolved.gridSelector;
|
||
}
|
||
return await page.evaluate(readTableScript(formNum, { maxRows, offset, gridSelector }));
|
||
}
|
||
|
||
/**
|
||
* Delete a row from the current table part.
|
||
* Single click to select the row, then Delete key to remove it.
|
||
*
|
||
* @param {number} row - 0-based row index to delete
|
||
* @param {Object} [options]
|
||
* @param {string} [options.tab] - Switch to this form tab before operating
|
||
* @returns {object} form state with { deleted, rowsBefore, rowsAfter }
|
||
*/
|
||
export async function deleteTableRow(row, { tab, table } = {}) {
|
||
ensureConnected();
|
||
await dismissPendingErrors();
|
||
const formNum = await page.evaluate(detectFormScript());
|
||
if (formNum === null) throw new Error('deleteTableRow: no form found');
|
||
|
||
// Pre-resolve grid when table is specified
|
||
let gridSelector;
|
||
if (table) {
|
||
const resolved = await page.evaluate(resolveGridScript(formNum, table));
|
||
if (resolved.error) throw new Error(`deleteTableRow: table "${table}" not found. Available: ${resolved.available?.map(a => a.name).join(', ') || 'none'}`);
|
||
gridSelector = resolved.gridSelector;
|
||
}
|
||
|
||
// 1. Switch tab if requested
|
||
if (tab) {
|
||
await clickElement(tab);
|
||
await page.waitForTimeout(500);
|
||
}
|
||
|
||
// 2. Find the target row and click to select it
|
||
const cellCoords = await page.evaluate(findDeleteRowCoordsScript(gridSelector, row));
|
||
|
||
if (cellCoords.error) throw new Error(`deleteTableRow: ${cellCoords.error}${cellCoords.total ? ' (total rows: ' + cellCoords.total + ')' : ''}`);
|
||
|
||
const rowsBefore = cellCoords.total;
|
||
|
||
// Pre-click Escape: leftover edit-mode from a prior fillTableRow Tab-navigation.
|
||
// Without it the next mouse click may not select the row reliably (the active
|
||
// edit input intercepts the event timing).
|
||
if (await isInputFocusedInGrid({ gridSelector })) {
|
||
await page.keyboard.press('Escape');
|
||
await page.waitForTimeout(150);
|
||
}
|
||
|
||
// Single click to select the row
|
||
await page.mouse.click(cellCoords.x, cellCoords.y);
|
||
await page.waitForTimeout(300);
|
||
|
||
// Post-click Escape: clicking a Number/Date cell auto-enters edit mode in 1С.
|
||
// Delete in edit mode clears the cell buffer instead of deleting the row, so
|
||
// we exit edit first. The row remains selected after Escape — Delete acts on it.
|
||
if (await isInputFocusedInGrid({ gridSelector })) {
|
||
await page.keyboard.press('Escape');
|
||
await page.waitForTimeout(150);
|
||
}
|
||
|
||
// 3. Press Delete to remove the row
|
||
await page.keyboard.press('Delete');
|
||
await waitForStable();
|
||
|
||
// 4. Count rows after deletion
|
||
const rowsAfter = await page.evaluate(countGridRowsScript(gridSelector));
|
||
|
||
return returnFormState({ deleted: row, rowsBefore, rowsAfter });
|
||
}
|