e2e/README.md
This directory contains all end-to-end (E2E) tests for GitButler. We use two different testing frameworks to cover different scenarios:
Before running E2E tests, ensure you have:
corepack enable in the project rootFrom the project root:
# Install all dependencies
pnpm install
# Install Playwright browsers (required for Playwright tests)
cd e2e
pnpm install-playwright
The E2E tests need a compiled version of the application:
# From project root - build the Rust backend
cargo build
# Build the frontend
pnpm build
Playwright tests run against the desktop application and test the UI interactions.
# From project root or e2e directory
pnpm test:e2e:playwright
# Run with Playwright UI mode (interactive debugging)
pnpm test:e2e:playwright:open
Playwright tests are located in playwright/tests/ and test the desktop Tauri application.
Blackbox tests use WebdriverIO to test the application in a more isolated manner:
# From project root
pnpm test:e2e:blackbox
# Or from e2e directory
pnpm run test:e2e:blackbox
These tests require the Tauri driver and test the application as a complete black box.
Tests for the web version of the application:
# From e2e directory
pnpm test:e2e:not-tauri
playwright/tests/:import { startGitButler, type GitButler } from "../src/setup.ts";
import { clickByTestId, waitForTestId } from "../src/util.ts";
import { expect, test } from "@playwright/test";
let gitbutler: GitButler;
test.afterEach(async () => {
await gitbutler?.destroy();
});
test("should do something amazing", async ({ page, context }, testInfo) => {
const workdir = testInfo.outputPath("workdir");
const configdir = testInfo.outputPath("config");
gitbutler = await startGitButler(workdir, configdir, context);
// Setup test data
await gitbutler.runScript("your-setup-script.sh");
await page.goto("/");
// Your test logic here
await waitForTestId(page, "your-element");
await clickByTestId(page, "your-button");
// Assertions
expect(await page.locator('[data-testid="result"]').textContent()).toBe("expected");
});
Add setup scripts if needed in playwright/scripts/ for test data preparation
Use test utilities from playwright/src/:
setup.ts: For starting GitButler instancesutil.ts: Helper functions for common UI interactionsenv.ts: Environment configurationblackbox/tests/:import { spawnAndLog, findAndClick, setElementValue } from "../utils.js";
describe("Your Feature", () => {
before(() => {
// Setup test repositories
spawnAndLog("bash", ["-c", "./blackbox/scripts/your-setup-script.sh ../target/debug/but"]);
});
it("should perform an action", async () => {
await findAndClick('button[data-testid="your-button"]');
const element = $('input[data-testid="your-input"]');
await setElementValue(await element.getElement(), "test value");
// Add assertions
const result = await $('div[data-testid="result"]').getElement();
await expect(result).toExist();
});
});
blackbox/scripts/ if you need to prepare test repositoriesplaywright/scripts/ - these are bash scripts that set up git repositoriesblackbox/scripts/ prepare test repositoriesplaywright/fixtures/data-testid attributes to elements you need to interact with in testsafterEach or after hooksThe easiest way to debug Playwright tests:
pnpm test:e2e:playwright:open
This opens Playwright's UI where you can:
Run tests with the browser visible:
# Set PLAYWRIGHT_UI environment variable
PLAYWRIGHT_UI=1 pnpm test:e2e:playwright
Run a single test file:
cd e2e
pnpm exec playwright test --config ./playwright/playwright.config.ts tests/yourTest.spec.ts
Run a specific test by name:
pnpm exec playwright test --config ./playwright/playwright.config.ts -g "test name pattern"
Add breakpoints in your test files and use VSCode's built-in debugger:
Tests automatically capture:
playwright.config.ts)Access these in e2e/test-results/ after test runs.
Add logging to your tests:
console.log("Debug info:", await page.locator('[data-testid="element"]').textContent());
View browser console in headed mode or check test output.
Blackbox tests record videos of test runs. Videos are saved in blackbox/videos/.
Edit timeouts in blackbox/wdio.blackbox.conf.ts:
mochaOpts: {
timeout: 120000; // Increase for debugging
}
cd e2e
pnpm exec wdio run ./blackbox/wdio.blackbox.conf.ts --spec ./blackbox/tests/your-test.spec.ts
Use browser.debug() in your test to pause execution:
it("should do something", async () => {
await findAndClick('button[data-testid="test"]');
await browser.debug(); // Pauses here
// ... rest of test
});
Tests timing out:
data-testid attributes existCannot find elements:
data-testid attributepage.locator() with a more general selector to verify element existsFlaky tests:
waitForTestId, waitForSelector)Application not starting:
cargo buildAfter a test run:
# Playwright artifacts
ls e2e/test-results/
# View Playwright trace
pnpm exec playwright show-trace e2e/test-results/path-to-trace.zip
# Blackbox videos
ls e2e/blackbox/videos/
You can also download them from the respective E2E Job on CI, or find a link in the "Upload Artifact" job log.
e2e/
├── playwright/ # Playwright tests for desktop app
│ ├── tests/ # Test files (*.spec.ts)
│ ├── src/ # Test utilities and helpers
│ │ ├── setup.ts # GitButler instance setup
│ │ ├── util.ts # UI interaction helpers
│ │ └── env.ts # Environment config
│ ├── scripts/ # Bash scripts for test setup
│ ├── fixtures/ # Test fixtures and data
│ └── playwright.config.ts # Playwright configuration
│
├── blackbox/ # Blackbox tests using WebdriverIO
│ ├── tests/ # Test files (*.spec.ts)
│ ├── scripts/ # Repository setup scripts
│ ├── utils.ts # Test utilities
│ ├── videos/ # Recorded test videos
│ └── wdio.blackbox.conf.ts # WDIO configuration
│
├── test-results/ # Test run artifacts
└── package.json # E2E package configuration
playwright/playwright.config.ts: Playwright test configurationblackbox/wdio.blackbox.conf.ts: WebdriverIO blackbox test configurationpackage.json: Test scripts and dependenciesE2E tests run in CI via GitHub Actions:
.github/workflows/test-e2e.yml: E2E tests (Playwright and blackbox)Tests run on push and pull requests with: