Ctrl K
ComunidadGuías…

agents-manage-ui/cypress/e2e/agent-tools.cy.ts

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

Archivo original ↗Preguntar a KiBot
/// <reference types="cypress" />

import { generateId } from '../../src/lib/utils/id-utils';

function dragNode(selector: string) {
  const dataTransfer = new DataTransfer();

  cy.get(selector)
    .invoke('attr', 'data-node-type')
    .then((nodeType) => {
      if (nodeType) {
        dataTransfer.setData('application/reactflow', JSON.stringify({ type: nodeType }));
      }
      dataTransfer.effectAllowed = 'move';

      cy.get(selector).should('be.visible').trigger('dragstart', { dataTransfer, force: true });

      // New nodes are created by ReactFlow's canvas-level onDrop handler on the pane,
      // not by dropping onto an existing node element. Drop into a known-empty region
      // of the pane instead of the pane center, which can already be occupied and flaky.
      cy.get('.react-flow__pane').then(($pane) => {
        const rect = $pane[0].getBoundingClientRect();
        const clientX = Math.min(rect.left + 240, rect.right - 80);
        const clientY = Math.min(rect.top + 200, rect.bottom - 80);

        cy.wrap($pane)
          .trigger('dragenter', { dataTransfer, clientX, clientY, force: true })
          .trigger('dragover', { dataTransfer, clientX, clientY, force: true })
          .trigger('drop', { dataTransfer, clientX, clientY, force: true });
      });
    });
}
function connectEdge(selector: string) {
  // React flow doesn't use onDragStart
  cy.get(selector).trigger('mousedown', { button: 0 });
  cy.get('[data-handleid="target-agent"]').trigger('mousemove').trigger('mouseup', { force: true });
}

describe('Agent Tools', () => {
  it('Editing sub-agent ID should not removes linked tools', () => {
    cy.visit('/default/projects/activities-planner');
    cy.contains('Create agent').click();
    cy.get('[name=name]').type(generateId(), { delay: 0 });
    cy.get('button[type=submit]').click();
    cy.get('[name$=".name"]').type('test', { delay: 0 });
    cy.get('.react-flow__node', { timeout: 20_000 }).should('have.length', 1);

    dragNode('[aria-label="Drag Function Tool node"]');
    cy.get('.react-flow__node', { timeout: 20_000 }).should('have.length', 2);
    connectEdge('[data-handleid="target-function-tool"]');
    cy.typeInMonaco('executeCode.js', 'function () {}');
    dragNode('[aria-label="Drag MCP node"]');
    cy.contains('Weather').click();
    connectEdge('[data-handleid="target-mcp"]');
    cy.contains('Connecting...').should('not.exist');
    cy.contains('Save changes').click();
    cy.contains('Agent saved', { timeout: 30_000 }).should('exist');
    cy.reload();
    cy.get('.react-flow__node', { timeout: 20_000 }).should('have.length', 3);
  });

  describe('Format', () => {
    it('JSON', () => {
      const uri = 'contextConfig.contextVariables.json';

      cy.visit('/default/projects/activities-planner/agents/activities-planner?pane=agent');
      cy.typeInMonaco(uri, '{"foo":123}');
      cy.get(`[data-uri="file:///${uri}"]`).prev().contains('Format').click();
      cy.assertMonacoContent(uri, '{\n  "foo": 123\n}');
    });
    it('JavaScript', () => {
      const uri = 'executeCode.js';

      cy.visit('/default/projects/activities-planner/agents/activities-planner?pane=agent');
      dragNode('[aria-label="Drag Function Tool node"]');
      cy.typeInMonaco(uri, 'function qux(){return"foo"}');
      cy.contains('Format').click();
      cy.assertMonacoContent(
        uri,
        `function qux() {
  return "foo";
}`
      );
    });

    it('Prompt', () => {
      const uri = 'prompt.template';

      cy.visit('/default/projects/activities-planner/agents/activities-planner?pane=agent');
      cy.typeInMonaco(uri, '#   hello   {{name}}');
      cy.contains('Format').click();
      cy.assertMonacoContent(uri, '# hello {{name}}');
    });
  });
});