Ctrl K
ComunidadGuías…

__tests__/inspector-list.test.js

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

Archivo original ↗Preguntar a KiBot
/**
 * A LIST OF RESULTS IS NOT ONE CONTROL DRAWN LARGE.
 *
 * look() keeps the biggest box in a cluster of overlapping ones, which is right and was itself a
 * fix: an <a> wrapper and its inner spans all cover the same place, and numbering each of them drew
 * five boxes for one button and produced dozens of phantom clicks.
 *
 * It is exactly wrong the other way round. Overlap is measured against the SMALLER box, so a card
 * inside a panel scores ~1.0 and is dropped in favour of the panel. Measured on Google Maps: look()
 * returned six elements and the fifth was one div holding every search result concatenated. The
 * agent could not click a single plumber, looked three times, and was forced to act by the observe
 * limiter with nothing to act on.
 *
 * Both halves are tested here, because a fix to one that breaks the other is not a fix.
 */
import { describe, it, expect } from 'vitest';
import { extractElements } from '../src/inspector.js';

const box = (text, top, left, width, height, extra = {}) => ({
  tag: 'a', type: null, id: null, selector: null, ariaLabel: '', placeholder: null, role: null,
  text, href: 'https://example.com', editable: false, on: false,
  left, top, width, height, ...extra,
});

const mkPage = (raw) => {
  const main = { evaluate: async () => raw };
  return {
    mainFrame: () => main,
    frames: () => [main],
    evaluate: async (fn) => {
      const s = String(fn);
      if (s.includes('innerWidth')) return 1280;
      if (s.includes('innerHeight')) return 800;
      return undefined;
    },
  };
};

const textsOf = (els) => els.map((e) => e.text);

describe('a panel of results', () => {
  it('OFFERS EVERY CARD, NOT THE PANEL THAT HOLDS THEM', async () => {
    /* Five plumbers stacked down a side panel, exactly the Maps shape: the panel wraps them all and
       each card sits wholly inside it. */
    const raw = [
      box('Hydraulik A Hydraulik B Hydraulik C Hydraulik D Hydraulik E', 100, 0, 400, 500, { tag: 'div' }),
      box('Hydraulik A', 100, 0, 380, 90),
      box('Hydraulik B', 200, 0, 380, 90),
      box('Hydraulik C', 300, 0, 380, 90),
      box('Hydraulik D', 400, 0, 380, 90),
      box('Hydraulik E', 500, 0, 380, 90),
    ];
    const got = textsOf(await extractElements(mkPage(raw)));
    expect(got).toContain('Hydraulik A');
    expect(got).toContain('Hydraulik E');
    /* And the container full of concatenated names is gone — it is not a thing you can click. */
    expect(got.some((t) => /Hydraulik A Hydraulik B/.test(t))).toBe(false);
  });
});

describe('one control drawn as several boxes', () => {
  it('stays ONE number — the behaviour that stopped the phantom clicks', async () => {
    /* A join button: the <a> wrapper and its inner spans all cover the same place. Numbering each
       made the agent read five indices as five buttons. */
    const raw = [
      box('Lid worden', 100, 100, 120, 40),
      box('Lid worden', 102, 102, 116, 36, { tag: 'span' }),
      box('Lid', 104, 104, 40, 32, { tag: 'span' }),
      box('worden', 104, 150, 60, 32, { tag: 'span' }),
    ];
    /* One NUMBER for the control, which is the property that matters. Counting every element
       returned would also be asserting things about decorative spans this fix never touched — and
       the original code answers those identically, so a count here tests the wrong thing. */
    const got = await extractElements(mkPage(raw));
    expect(got.filter((e) => e.text === 'Lid worden').length).toBe(1);
  });

  it('does not split a button into its icon and its label', async () => {
    /* The trap in the obvious fix. An icon and a label do not overlap EACH OTHER, so "children that
       sit apart" alone would cut every button in half. A stack has one place; a list has several,
       and the parent of a list is far bigger than any one of its children. */
    const raw = [
      box('Download', 100, 100, 140, 40),
      box('', 108, 106, 24, 24, { tag: 'span' }),
      box('Download', 108, 136, 90, 24, { tag: 'span' }),
    ];
    const got = await extractElements(mkPage(raw));
    expect(got.filter((e) => e.text === 'Download').length).toBe(1);
  });

  it('keeps a tall wrapper that only holds one real control', async () => {
    /* Three children, but the wrapper is barely bigger than the largest of them — a stack, not a
       list, and splitting it would hand back fragments of one button. */
    const raw = [
      box('Publiceren', 100, 100, 200, 60),
      box('Publiceren', 105, 105, 190, 50, { tag: 'span' }),
      box('', 110, 110, 20, 20, { tag: 'span' }),
      box('nu', 110, 260, 20, 20, { tag: 'span' }),
    ];
    const got = await extractElements(mkPage(raw));
    expect(got.filter((e) => e.text === 'Publiceren').length).toBe(1);
  });
});