Ctrl K
ComunidadGuías…

__tests__/read-table.test.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/**
 * READING A TABLE AS DATA — the tool that stops numbers being retyped out of prose.
 *
 * `read` hands the page back as text and the model picks the figures out of it. For a paragraph that
 * is fine. For a table of numbers it is the one step in the chain that can be silently wrong: a
 * column off by one, a separator read as a decimal point, a wrapped row skipped. Nothing downstream
 * can tell, because a wrong impression count looks exactly like a right one.
 *
 * It is also the slow way. Reading a Search Console report by eye was look → read → scroll → read,
 * and that loop is most of the difference between a four-step walk and the 166-step one we measured.
 */
import { describe, it, expect } from 'vitest';
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';

const read = (rel) => readFileSync(fileURLToPath(new URL(rel, import.meta.url)), 'utf8');
const perceive = read('../src/tools/perceive.js');
const agent = read('../src/agent.js');
const roles = read('../src/roles.js');

describe('the table reader returns cells, not a summary', () => {
  it('it finds a plain table and an ARIA grid, which is what component libraries render', () => {
    expect(perceive).toMatch(/document\.querySelectorAll\('table,\[role="table"\],\[role="grid"\],\[role="treegrid"\]'\)/);
    expect(perceive).toMatch(/\[role="cell"\],\[role="gridcell"\]/);
  });

  /* A nested table's cells belong to the nested table, or every row reads as one enormous row. */
  it('and a nested table does not swallow its parent', () => {
    expect(perceive).toMatch(/cs\.filter\(\(c\) => c\.closest\('\[role="row"\],tr'\) === row\)/);
    expect(perceive).toMatch(/rs\.filter\(\(r\) => r\.closest\('table,\[role="table"\],\[role="grid"\],\[role="treegrid"\]'\) === t\)/);
  });

  /* A header alone is not a table worth returning, and an invisible one is not on the page. */
  it('an empty or hidden table is not offered', () => {
    expect(perceive).toMatch(/if \(rows\.length < 2\) continue;/);
    expect(perceive).toMatch(/st\.display !== 'none' && st\.visibility !== 'hidden' && Number\(st\.opacity\) !== 0/);
  });

  it('the cells are handed over verbatim, with the arithmetic forbidden', () => {
    expect(perceive).toMatch(/never round, convert or add them up/);
  });

  /* Frames, for the same reason `read` walks them: a dashboard's content often lives in one. */
  it('and a table inside a frame is still found', () => {
    expect(perceive).toMatch(/for \(const fr of ctx\.page\(\)\.frames\(\)\)/);
  });

  it('an empty page says so, and says what to do instead of clicking about', () => {
    expect(perceive).toMatch(/There is no table on this page/);
    expect(perceive).toMatch(/open the right one rather than clicking about/);
  });
});

describe('every role that can read a page can read a table', () => {
  it('it is one of the hands, and it changes nothing', () => {
    expect(roles).toMatch(/const HANDS = \['look', 'read', 'read_table',/);
    expect(agent).toMatch(/const OBSERVE_ONLY = new Set\(\['look', 'read', 'read_table',/);
  });

  it('the model is told to prefer it for figures', () => {
    expect(agent).toMatch(/name: 'read_table'/);
    expect(agent).toMatch(/instead of read: the figures come back verbatim rather than retyped/);
  });

  /* The reader that measured the cost of not having it. */
  it('and the search console reader is told to use it rather than read', () => {
    const role = roles.slice(roles.indexOf("'reach.search': {"), roles.indexOf("'gsc.audit': {"));
    expect(role).toMatch(/USE read_table, NOT read/);
    expect(role).toMatch(/Never round them, never convert them, never add them up/);
    /* `read` keeps one honest job: saying the property has no data yet. */
    expect(role).toMatch(/Plain read is for when you need to explain something the table does not show/);
  });
});