Files
composiohq__composio/ts/e2e-tests
Alberto Schiabel 956f9be9b4 chore(agents): normalize repo guidance skills (#3666)
This PR:
- replaces the duplicated repo-local skill set with the requested
canonical `.agents/skills` taxonomy and short router `SKILL.md` files
backed by first-level references
- makes `.claude/skills` a compatibility symlink to `.agents/skills` and
removes hand-maintained Claude skill/rule copies
- moves docs agent guidance and decisions into neutral
`docs/agent-guidance/` and `docs/decisions/`, with `docs/CLAUDE.md`
reduced to a shim
- retires CLI Cursor rules after migrating CLI design, Effect source,
and client-cache sync guidance into `AGENTS.md` and `cli-command`
- adds nested `AGENTS.md` files for TS, core, providers, e2e, Python,
Python providers, and docs
- adds `pnpm validate:agent-skills` to validate skill frontmatter,
taxonomy, references, symlink invariants, stale paths, and command names
- implements missing Python `tst` and `snt` nox sessions that existing
Makefile targets already exposed
- no changeset: repository guidance/tooling only, no published SDK
package behavior

## Verification
- `pnpm validate:agent-skills` -> `Validated 14 canonical agent skills
and guidance invariants.`
- `for skill in .agents/skills/*; do python
/Users/jkomyno/.codex/skills/.system/skill-creator/scripts/quick_validate.py
"$skill" || exit 1; done` -> 14x `Skill is valid!`
- `pnpm --dir ts/packages/cli validate:skills` -> `Validated
composio-cli skill builds for stable and beta.`
- `cd python && uv run nox --list` -> includes `tst` and `snt`
- `cd python && uv run nox -s snt` -> 18 passed
- `cd python && uv run nox -s tst -- tests/test_imports.py` -> 8 passed
- `git diff --check` / `git diff --cached --check` -> clean
- stale reference search for retired docs/Claude/Cursor paths -> no
matches

## Forward Tests
- TypeScript core bug: loaded `bug-fixing`, `typescript-sdk`,
`typescript-testing`; found correct root/ts/core `AGENTS.md` route.
- Python provider: loaded `python-providers`, `python-testing`; found
missing nox sessions, fixed here.
- CLI command: loaded `cli-command`; found recording/changeset wording
gaps, fixed here.
- Cross-SDK drift: loaded `cross-sdk-parity`; again found Python nox
drift, fixed here.
- Docs + decision: loaded `docs-decisions`; found decision
template/index and Twoslash path gaps, fixed here.

## Notes
The first normal `git commit` attempt hit a lint-staged/Git stash
limitation while replacing `.claude/skills/` with a symlink (`path ...
beyond a symbolic link`). The final commit used `--no-verify` after the
validators and formatting checks above passed.
2026-06-27 00:35:57 +04:00
..
2026-05-05 14:44:43 +05:30

E2E Tests

End-to-end tests for @composio/core and the CLI across different runtimes.

Directory Structure

ts/e2e-tests/
├── _utils/                                  # Shared test infrastructure
│   ├── Dockerfile.node                      # Docker image for Node.js tests
│   ├── Dockerfile.deno                      # Docker image for Deno tests
│   ├── Dockerfile.cli                       # Docker image for CLI tests (scratch)
│   ├── scripts/                             # Docker build and cleanup scripts
│   │   ├── docker-build.ts                  # Pre-build images for all Node/Deno/CLI versions
│   │   └── docker-clean.ts                  # Remove all e2e Docker images
│   ├── src/                                 # TypeScript runner utilities
│   │   ├── config.ts                        # Configuration utilities
│   │   ├── const.ts                         # Well-known Node.js/Deno versions and timeouts
│   │   ├── e2e.ts                           # Main e2e test entry point
│   │   ├── image-lifecycle.ts               # Docker image build/run utilities
│   │   ├── index.ts                         # Public exports
│   │   ├── runner.ts                        # Docker test runner
│   │   ├── sanitize.ts                      # Output sanitization utilities
│   │   ├── types.ts                         # TypeScript type definitions
│   │   └── volume.ts                        # Docker volume management
│   └── README.md                            # Utils documentation
├── runtimes/
    ├── node/                                # Node.js runtime tests
    │   ├── cjs-basic/                       # Node.js 22 require(esm) interop tests
    │   ├── claude-agent-sdk/                # @composio/claude-agent-sdk + Claude Agent SDK MCP tests
    │   ├── custom-tools/                    # Custom local tools execution (session.execute, proxyExecute, Zod validation)
    │   ├── esm-basic/                       # ESM compatibility tests
    │   ├── json-schema-to-zod-v3/           # @composio/json-schema-to-zod + Zod v3 tests
    │   ├── json-schema-to-zod-v4/           # @composio/json-schema-to-zod + Zod v4 tests
    │   ├── mastra-tool-router-zod-v3/       # @composio/mastra Tool Router + Zod v3 tests
    │   ├── mastra-tool-router-zod-v4/       # @composio/mastra Tool Router + Zod v4 tests
    │   ├── openai-zod4-compat/              # OpenAI + Zod v4 compatibility tests
    │   ├── tool-router-files/              # Tool Router session files (list, upload, download, delete)
    │   ├── tool-router-pagination/          # Tool Router session.toolkits() cursor pagination
    │   └── typescript-mjs-import-nodenext/  # TypeScript moduleResolution: nodenext tests
    ├── deno/                                # Deno runtime tests
    │   └── esm-basic/                       # ESM compatibility tests via npm: specifier
    └── cloudflare/                          # Cloudflare runtime tests
        ├── cf-workers-basic/                # Basic Cloudflare Workers tests
        ├── cf-workers-files/                # Cloudflare Workers file handling tests
        └── cf-workers-tool-router-ai/       # Cloudflare Workers AI SDK tool router tests
└── cli/                                     # CLI runtime tests (scratch)
    ├── version/                             # composio version command tests
    ├── whoami/                              # composio whoami command tests
    └── toolkits/                            # composio toolkits command tests
        ├── list/                            # composio toolkits list tests
        ├── info/                            # composio toolkits info tests
        └── search/                          # composio toolkits search tests

Running Tests

All E2E Tests

pnpm test:e2e

Node.js Tests Only

pnpm test:e2e:node

Runs Node.js tests in Docker using bun test. The default Node.js version is determined by mise.toml.

To run with a specific Node.js version:

COMPOSIO_E2E_NODE_VERSION=22.22.3 pnpm test:e2e:node

Deno Tests Only

pnpm test:e2e:deno

Runs Deno tests in Docker using bun test. The default Deno version is determined by mise.toml.

To run with a specific Deno version:

COMPOSIO_E2E_DENO_VERSION=2.6.7 pnpm test:e2e:deno

Cloudflare Workers Tests Only

pnpm test:e2e:cloudflare

CLI Tests Only

pnpm test:e2e:cli

To run with a specific CLI version:

COMPOSIO_E2E_CLI_VERSION=0.1.24 pnpm test:e2e:cli

Adding New Tests

Node.js Runtime Tests

  1. Create a new directory under runtimes/node/ (e.g., runtimes/node/my-test)
  2. Add a package.json with name @e2e-tests/node-my-test
  3. Add test:e2e and test:e2e:node scripts
  4. Create an e2e.test.ts file with inline configuration:
import { e2e, type E2ETestResult } from '@e2e-tests/utils';
import { TIMEOUTS } from '@e2e-tests/utils/const';
import { describe, it, expect, beforeAll } from 'bun:test';

e2e(import.meta.url, {
  versions: {
    node: ['22.22.3', '24.17.0', '25.9.0'], // Optional: defaults to the current version in mise.toml
  },
  env: { MY_VAR: process.env.MY_VAR }, // Optional: env vars (validated at startup)
  defineTests: ({ runtime, runFixture }) => {
    let result: E2ETestResult;

    beforeAll(async () => {
      result = await runFixture({ filename: 'fixtures/test.mjs' });
    }, TIMEOUTS.FIXTURE);

    describe('output', () => {
      it('exits successfully', () => {
        expect(result.exitCode).toBe(0);
      });

      it('contains expected output', () => {
        expect(result.stdout).toContain('expected text');
      });
    });
  },
});
  1. Add fixture files in a fixtures/ directory

Deno Runtime Tests

  1. Create a new directory under runtimes/deno/ (e.g., runtimes/deno/my-test)
  2. Add a package.json with name @e2e-tests/deno-my-test
  3. Add test:e2e and test:e2e:deno scripts
  4. Create an e2e.test.ts file with inline configuration:
import { e2e, type E2ETestResult } from '@e2e-tests/utils';
import { TIMEOUTS } from '@e2e-tests/utils/const';
import { describe, it, expect, beforeAll } from 'bun:test';

e2e(import.meta.url, {
  versions: {
    deno: ['2.6.7'], // Optional: defaults to the current version in mise.toml
  },
  usesFixtures: true,
  defineTests: ({ runtime, runFixture }) => {
    let result: E2ETestResult;

    beforeAll(async () => {
      result = await runFixture({ filename: 'test.ts' });
    }, TIMEOUTS.FIXTURE);

    describe('output', () => {
      it('exits successfully', () => {
        expect(result.exitCode).toBe(0);
      });

      it('contains expected output', () => {
        expect(result.stdout).toContain('expected text');
      });
    });
  },
});
  1. Add fixture files in a fixtures/ directory. Fixtures use Deno's npm: specifier to import packages.

Tests with External Dependencies (npm install)

For tests that need to install npm packages at runtime, use usesFixtures: true and the setup option:

import { e2e, type E2ETestResultWithSetup } from '@e2e-tests/utils';
import { TIMEOUTS } from '@e2e-tests/utils/const';
import { describe, it, expect, beforeAll } from 'bun:test';

e2e(import.meta.url, {
  versions: {
    node: ['22.22.3', '24.17.0', '25.9.0'],
  },
  usesFixtures: true, // Sets cwd to fixtures/ directory
  env: { MY_API_KEY: process.env.MY_API_KEY },
  defineTests: ({ runFixture }) => {
    let result: E2ETestResultWithSetup;

    beforeAll(async () => {
      result = await runFixture({
        filename: 'index.mjs',
        setup: 'npm install --legacy-peer-deps', // Runs before fixture
      });
    }, TIMEOUTS.FIXTURE);

    describe('setup', () => {
      it('npm install completes successfully', () => {
        expect(result.setup.exitCode).toBe(0);
      });
    });

    describe('fixture', () => {
      it('exits successfully', () => {
        expect(result.exitCode).toBe(0);
      });
    });
  },
});

Cloudflare Runtime Tests

  1. Create a new directory under runtimes/cloudflare/ (e.g., runtimes/cloudflare/my-test)
  2. Add a package.json with name @e2e-tests/cf-my-test
  3. Add test:e2e and test:e2e:cloudflare scripts
  4. Configure vitest with @cloudflare/vitest-pool-workers

CLI Runtime Tests

  1. Create a new directory under cli/ (e.g., cli/my-test)
  2. Add a package.json with name @e2e-tests/cli-my-test
  3. Add test:e2e and test:e2e:cli scripts
  4. Create an e2e.test.ts file with inline configuration:
import { e2e, sanitizeOutput, type E2ETestResult } from '@e2e-tests/utils';
import { TIMEOUTS } from '@e2e-tests/utils/const';
import { describe, it, expect, beforeAll } from 'bun:test';

e2e(import.meta.url, {
  versions: {
    cli: ['current'],
  },
  defineTests: ({ runCmd }) => {
    let result: E2ETestResult;

    beforeAll(async () => {
      result = await runCmd('composio version');
    }, TIMEOUTS.FIXTURE);

    describe('output', () => {
      it('exits successfully', () => {
        expect(result.exitCode).toBe(0);
      });

      it('stdout matches snapshot', () => {
        expect(sanitizeOutput(result.stdout)).toMatchSnapshot();
      });
    });
  },
});

Debugging

Each test suite generates an ephemereal DEBUG.log file in its directory with structured output:

================================================================================
E2E Test: my-test
Started: 2026-01-30T12:18:42.000Z
Test file: ts/e2e-tests/runtimes/node/my-test/e2e.test.ts
Runtime versions: Node.js 22.22.3, Node.js 24.17.0, Node.js 25.9.0
================================================================================

################################################################################
### Node.js 22.22.3
################################################################################
Image: composio-e2e-node:22.22.3

--- Phase 1/2: setup ---
Container: e2e-my-test-22-22-3-1769775520382-setup
Command: npm install
Duration: 2.55s
Exit Code: 0 (success)

[stdout]
added 3 packages in 2s

[stderr]
(empty)

--- Phase 2/2: fixture ---
Container: e2e-my-test-22-22-3-1769775520382-fixture
Command: node index.mjs
Duration: 0.56s
Exit Code: 0 (success)

[stdout]
Test passed!

[stderr]
(empty)

================================================================================
Summary
================================================================================
Node.js 22.22.3: PASS (2 phases, 3.11s total)
Node.js 24.17.0: PASS (2 phases, 3.09s total)
Node.js 25.9.0: PASS (2 phases, 3.08s total)

Finished: 2026-01-30T12:18:46.500Z
Total duration: 4.50s
================================================================================