Skip to content

/e2e-testing

End-to-end testing for Falcon Foundry apps using Playwright and @crowdstrike/foundry-playwright. TRIGGER when user asks to "add e2e tests", "add playwright tests", "write end-to-end tests", "test my app", or mentions "e2e", "playwright", or "end-to-end" in the context of testing

shell
$ npx -y skills add CrowdStrike/foundry-skills --skill e2e-testing --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/e2e-testing
How auto-invocation works

Context preview

The summary Claude sees to decide when to auto-load this skill.

End-to-end testing for Falcon Foundry apps using Playwright and @crowdstrike/foundry-playwright. TRIGGER when user asks to "add e2e tests", "add playwright tests", "write end-to-end tests", "test my app", or mentions "e2e", "playwright", or "end-to-end" in the context of testing

SKILL.md

e2e-testing.SKILL.md
name: e2e-testing
description: End-to-end testing for Falcon Foundry apps using Playwright and @crowdstrike/foundry-playwright. TRIGGER when user asks to "add e2e tests", "add playwright tests", "write end-to-end tests", "test my app", or mentions "e2e", "playwright", or "end-to-end" in the context of testing a Foundry app. DO NOT TRIGGER during normal app creation, UI development, or function development. This skill is opt-in; not all apps need e2e tests.
version: 1.4.0
updated: 2026-07-31
tags: [foundry, e2e, playwright, testing]
author: CrowdStrike
license: MIT
compatibility: Claude Code >=1.0
metadata:
  category: testing

Foundry E2E Testing

End-to-end testing for Falcon Foundry apps using [Playwright](https://playwright.dev/) and the [`@crowdstrike/foundry-playwright`](https://github.com/CrowdStrike/foundry-playwright) library.

The library provides authentication, app install/uninstall, page objects, and configuration so each app only writes its app-specific tests.

Quick Start

1. Create the `e2e/` directory

my-foundry-app/
├── e2e/
│   ├── .env                    # Local credentials (git-ignored)
│   ├── .env.sample             # Template for other developers
│   ├── .gitignore
│   ├── package.json
│   ├── playwright.config.ts
│   └── tests/
│       └── foundry.spec.ts
├── manifest.yml
└── ...

2. `package.json`

Node.js LTS is recommended.

{
  "name": "playwright-foundry",
  "version": "1.0.0",
  "scripts": {
    "test": "npx playwright test",
    "test:ui": "npx playwright test --ui",
    "test:debug": "npx playwright test --debug",
    "test:verbose": "DEBUG=true npx playwright test --reporter=list"
  },
  "type": "commonjs",
  "devDependencies": {
    "@crowdstrike/foundry-playwright": "0.5.0",
    "@types/node": "25.6.0"
  }
}

**Always pin exact versions** — never use `"latest"`, `"^"`, or `"~"`. Check npm for the current version of each package.

The library brings `@playwright/test`, `@dotenvx/dotenvx`, and `otpauth` as transitive dependencies. No need to install them separately.

3. `.env`

FALCON_USERNAME=your.email@company.com
FALCON_PASSWORD=your-password
FALCON_AUTH_SECRET=your-totp-secret
FALCON_BASE_URL=https://falcon.us-2.crowdstrike.com
APP_NAME=your-app-name

**Convention for sample apps:** Set `APP_NAME` to match the manifest `name` field, which should match the repo name (e.g., `foundry-sample-functions-python`). This avoids spaces in names and simplifies CI. This is a convention, not a hard requirement.

4. `playwright.config.ts`

import { defineFoundryConfig } from '@crowdstrike/foundry-playwright';

export default defineFoundryConfig();

This gives you the standard 4-project pipeline automatically: 1. **setup**: authenticate and save session state 2. **app-install**: install the app via App Catalog 3. **chromium**: run your tests 4. **app-uninstall**: clean up after tests

5. `.gitignore`

node_modules/
playwright/.auth/
playwright-report/
test-results/
.env

6. Install and run

cd e2e
npm install
npx playwright install chromium --with-deps
npm test

Writing Tests

Available page objects

The library provides these page objects:

| Class | Purpose | |-------|---------| | `WorkflowsPage` | Search, open, execute, and verify Falcon Fusion SOAR workflows | | `DetectionExtensionPage` | Navigate to Endpoint Detections, expand extensions, return iframe FrameLocator | | `HostManagementPage` | Navigate to host management, retrieve host IDs | | `AppCatalogPage` | Install, uninstall, and navigate to apps | | `AppBuilderPage` | Disable workflow provisioning before install | | `AppManagerPage` | Find and navigate to apps in App Manager | | `FoundryHomePage` | Navigate to Falcon Foundry home |

Fixtures pattern

Create `src/fixtures.ts` to wire up page objects as Playwright fixtures. **Only import what your tests actually use** — don't define unused fixtures:

import { test as baseTest } from '@playwright/test';
import { DetectionExtensionPage, WorkflowsPage } from '@crowdstrike/foundry-playwright';

type FoundryFixtures = {
  detectionExtensionPage: DetectionExtensionPage;
  workflowsPage: WorkflowsPage;
};

export const test = baseTest.extend<FoundryFixtures>({
  detectionExtensionPage: async ({ page }, use) => { await use(new DetectionExtensionPage(page)); },
  workflowsPage: async ({ page }, use) => { await use(new WorkflowsPage(page)); },
});

export { expect } from '@playwright/test';

Playwright fixtures are lazy (only instantiated when a test requests them), so unused fixtures don't hurt performance — but they add confusion and dead code. Add fixtures as you add tests that need them.

Example test: workflows

import { test } from '../src/fixtures';

test.describe.configure({ mode: 'serial' });

test('should execute workflow', async ({ workflowsPage }) => {
  test.setTimeout(180000);
  await workflowsPage.navigateToWorkflows();
  await workflowsPage.executeAndVerifyWorkflow('My Workflow Name');
  await workflowsPage.verifyWorkflowExecutionCompleted();
});

test('should execute workflow with input', async ({ workflowsPage, hostManagementPage }) => {
  test.setTimeout(180000);
  const hostId = await hostManagementPage.getFirstHostId();
  if (!hostId) { test.skip(true, 'No hosts available'); return; }

  await workflowsPage.navigateToWorkflows();
  await workflowsPage.executeAndVerifyWorkflow('Host Details Workflow', {
    inputs: { 'Host ID': hostId },
  });
  await workflowsPage.verifyWorkflowExecutionCompleted();
});

`executeAndVerifyWorkflow()` handles search, execution trigger, and initial verification. `verifyWorkflowExecutionCompleted()` opens the execution detail view in a new tab and polls until the status leaves "In Progress" — it fails the test if the execution reports "Failed" and times out after 120s by default. For render-only checks (e.g., ServiceNow workflows without credentials), use `verifyW

Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withcrowdstrike-falcon-foundry

AI coding assistant skills for building CrowdStrike Falcon Foundry apps. Build Foundry apps from a natural language prompt — API integrations, workflows, UI pages, functions, and collections — all scaffolded with the Foundry CLI and deployed to the Falcon

Get the whole plugin, auto-invoked