Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
6cfe8de
feat: allow enum charts
maximka76667 Mar 16, 2026
d4cd711
fix: command item's params state reset
maximka76667 Mar 17, 2026
dce9ef1
fix: fix chart surface for enums
maximka76667 Mar 17, 2026
9204367
feat: increase frontend startup delay, close app on main window close…
maximka76667 Mar 17, 2026
407bb23
feat: change release name
maximka76667 Mar 17, 2026
1326ac9
fix: oops
maximka76667 Mar 17, 2026
5234588
fix: add return for branches fetching function
maximka76667 Mar 18, 2026
dc9e07b
feat: add 2 seconds timeout for fetch
maximka76667 Mar 18, 2026
a0a2c1b
refact: change path logs with debug
maximka76667 Mar 18, 2026
d8f0bce
test: add tests to paths.js in electron and filters logic in testing-…
maximka76667 Mar 21, 2026
1a3cde5
feat: make command inputs empty dy default
maximka76667 Mar 21, 2026
883fef5
test(testing-view): add tests for charts store slice
maximka76667 Mar 21, 2026
8651b22
tests(e2e): add some basic e2e tests for ui
maximka76667 Mar 21, 2026
f94977d
fix: fix empty parameters for keyboard shortcut crash
maximka76667 Mar 21, 2026
b0d8fcc
fix: make backend wait on server start, change workflows to execute e…
maximka76667 Mar 21, 2026
df787b4
fix: install electron
maximka76667 Mar 21, 2026
28739f2
feat: add electron tests and fix e2e tests
maximka76667 Mar 21, 2026
9504dc4
chore: more deps
maximka76667 Mar 21, 2026
0c3fe08
fix
maximka76667 Mar 21, 2026
f8820b5
fix: disable sandbox on any linux
maximka76667 Mar 21, 2026
03b2223
test: debug dependencies
maximka76667 Mar 21, 2026
dcc4ee0
test: try no sandbox
maximka76667 Mar 21, 2026
f6b0e73
feat: change e2e machine to macos
maximka76667 Mar 21, 2026
4759aed
fix: build binary
maximka76667 Mar 21, 2026
1637064
fix: disable devtools
maximka76667 Mar 21, 2026
6a64f7e
debug
maximka76667 Mar 21, 2026
c341932
fix: copy dir
maximka76667 Mar 21, 2026
2003b6a
test: return back all ui tests
maximka76667 Mar 21, 2026
1a18cf1
feat: add http ready message
maximka76667 Mar 21, 2026
b4d5035
test: debug backend executable
maximka76667 Mar 21, 2026
d645b4e
test: debug backend
maximka76667 Mar 21, 2026
661c62c
test
maximka76667 Mar 21, 2026
ae0fd41
fix: disable python test
maximka76667 Mar 21, 2026
4119299
fix: add 0.9 alias
maximka76667 Mar 21, 2026
58bb796
feat: remove active badge test and try to fix local storage test
maximka76667 Mar 21, 2026
b0df377
test: debug localstorage
maximka76667 Mar 21, 2026
48807f7
fix: disable FORCE DEV
maximka76667 Mar 21, 2026
642d766
Update e2e-tests.yaml
maximka76667 Mar 21, 2026
8de6cbe
test: debug backend
maximka76667 Mar 21, 2026
809fdf6
test
maximka76667 Mar 21, 2026
5a5c437
feat: add timeout
maximka76667 Mar 21, 2026
e0de9a5
feat: remove backend error suppresion
maximka76667 Mar 21, 2026
b1f537d
feat: add backend url to .env
maximka76667 Mar 21, 2026
68f1cd5
feat: finally fix tests
maximka76667 Mar 21, 2026
6cdb6d3
feat: remove branch patching
maximka76667 Mar 21, 2026
27b4502
chore: remove it
maximka76667 Mar 21, 2026
11b7840
feat: add all selected functionality
maximka76667 Mar 21, 2026
8cba11d
feat: folder button
maximka76667 Mar 21, 2026
6aad3c3
docs: add documentation for e2e and testing-view
maximka76667 Mar 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions .github/workflows/e2e-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: E2E Tests

on:
pull_request:
branches:
- main
- develop
- production
- "frontend/**"
- "control-station/**"
- "testing-view/**"
- "e2e/**"
paths:
- "frontend/testing-view/**"
- "electron-app/**"
- "e2e/**"
- "pnpm-lock.yaml"
- ".github/workflows/e2e-tests.yaml"

jobs:
e2e:
name: Playwright E2E Tests
runs-on: macos-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: "1.23"

- name: Build backend binary
run: |
mkdir -p electron-app/binaries
cd backend/cmd && go build -o ../../electron-app/binaries/backend-darwin-arm64 .

- name: Patch backend config
run: sed -i '' 's/validate = true/validate = false/' backend/cmd/dev-config.toml

- name: Add loopback aliases required by backend
run: sudo ifconfig lo0 alias 127.0.0.9

- name: Debug - test backend binary
run: |
./electron-app/binaries/backend-darwin-arm64 --config backend/cmd/dev-config.toml 2>&1 &
PID=$!
sleep 5
kill $PID 2>/dev/null || true
continue-on-error: true

- uses: pnpm/action-setup@v4

- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "pnpm"

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Install Electron binary
run: node node_modules/electron/install.js
working-directory: e2e

- name: Debug - verify Electron binary
run: |
node -e "const e = require('electron'); console.log('Electron path:', e);"
ls -la "$(node -e "process.stdout.write(require('electron'))")"
working-directory: e2e

- name: Build testing-view (e2e mode)
run: |
pnpm --filter testing-view build:e2e
mkdir -p electron-app/renderer/testing-view
cp -r frontend/testing-view/dist/. electron-app/renderer/testing-view/

- name: Run UI tests
run: pnpm --filter e2e exec playwright test tests/ui/

- name: Upload test report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: e2e/playwright-report/
retention-days: 7
34 changes: 34 additions & 0 deletions .github/workflows/electron-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Electron Tests

on:
pull_request:
branches:
- main
- develop
- production
- "frontend/**"
- "control-station/**"
- "testing-view/**"
paths:
- "electron-app/**"
- ".github/workflows/electron-tests.yaml"

jobs:
test:
name: Run Electron Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v4

- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "pnpm"

- name: Install dependencies
run: pnpm install --frozen-lockfile --filter=hyperloop-control-station

- name: Run tests
run: pnpm test --filter=hyperloop-control-station
12 changes: 1 addition & 11 deletions .github/workflows/frontend-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,9 @@ on:
- "pnpm-lock.yaml"
- ".github/workflows/frontend-tests.yaml"

push:
branches:
- "frontend/**"
- "testing-view/**"
- "competition-view/**"
paths:
- "frontend/**"
- "pnpm-lock.yaml"
- ".github/workflows/frontend-tests.yaml"

jobs:
test:
name: Run Frontend Tests
name: Run Frontend Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ jobs:
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.determine-version.outputs.version }}
name: Hyperloop Control Station v${{ needs.determine-version.outputs.version }}
name: Control Station v${{ needs.determine-version.outputs.version }}
draft: ${{ needs.determine-version.outputs.is_draft }}
generate_release_notes: true
files: dist/**/*
Expand Down
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Our `pnpm-workspace.yaml` defines the following workspaces:
| `backend` | Go | Data ingestion and pod communication server |
| `packet-sender` | Rust | Utility for simulating vehicle packets |
| `hyperloop-control-station` | JS | The main Control Station electron desktop application |
| `e2e` | TS | End-to-end tests for the whole app (Playwright) |
| `@workspace/ui` | TS/React | Shared UI component library (frontend-kit) |
| `@workspace/core` | TS | Shared business logic and types (frontend-kit) |
| `@workspace/eslint-config` | ESLint | Common ESLint configuration (frontend-kit) |
Expand Down Expand Up @@ -57,9 +58,19 @@ All Turbo scripts support filtering to target specific workspaces:
#### Lifecycle Scripts

- `pnpm build` – Compiles every package in the monorepo (Go binaries, Rust crates, and Vite apps).
- `pnpm test` – Runs all test suites across the repo (Vitest, Go tests, and Cargo tests).
- `pnpm test` – Runs all test suites across the repo (Vitest, Go tests, Cargo tests, and Playwright e2e tests).
- `pnpm lint` – Runs ESLint across all TypeScript packages.
- `pnpm preview` – Previews the production Vite builds for the frontend applications.

#### Electron App Scripts

- `pnpm start` – Launches the Electron app directly (requires a prior build).
- `pnpm build:win` – Packages the Electron app for Windows.
- `pnpm build:linux` – Packages the Electron app for Linux.
- `pnpm build:mac` – Packages the Electron app for macOS.

#### Utility Scripts

- `pnpm ui:add <component-name>` - To add shadcn/ui components

> Note: don't forget to also include it in frontend-kit/ui/src/components/shadcn/index.ts to be able to access it from @workspace/ui
1 change: 1 addition & 0 deletions backend/cmd/setup_vehicle.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ func configureHTTPServer(
)

httpServer := h.NewServer(server.Addr, mux)
trace.Info().Str("localAddr", server.Addr).Msg("http server listening")
go httpServer.ListenAndServe()
}

Expand Down
3 changes: 3 additions & 0 deletions e2e/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
playwright-report/
test-results/
57 changes: 57 additions & 0 deletions e2e/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# e2e

End-to-end tests for the whole app. Tests run against the real Electron application using **Playwright** with the `@playwright/test` electron driver.

---

## Overview

Tests are split into two Playwright projects:

| Project | Directory | Description |
| :------------ | :--------------- | :------------------------------------------------------------ |
| `ui` | `tests/ui/` | UI tests — launch the Electron app and interact with the UI |
| `integration` | `tests/integration/` | Integration tests (reserved for future use) |

---

## UI Tests

These tests launch the full Electron app and drive it through Playwright. They cover app startup, window titles, mode badge state, chart interactions, and filter dialog behaviour.

---

## Fixtures

`fixtures/electron.ts` provides three custom Playwright fixtures:

| Fixture | Description |
| :--------- | :------------------------------------------------------------------ |
| `app` | Launches the Electron app and waits for both windows to be ready |
| `page` | The main Control Station window — waits for the app to leave loading state |
| `logPage` | The Backend Logs window |

---

## Scripts

| Script | Description |
| :--------------------- | :---------------------------------------------------------------- |
| `pnpm test` | Build all dependencies then run all tests |
| `pnpm test:ui` | Build all dependencies then run only `tests/ui` |
| `pnpm test:integration`| Build the electron app then run only `tests/integration` |
| `pnpm test:fast` | Run all tests without rebuilding (assumes already built) |
| `pnpm test:fast:ui` | Run `tests/ui` without rebuilding |
| `pnpm report` | Open the last Playwright HTML report |

> **Note:** `pnpm test` and `pnpm test:ui` always build the `testing-view` (e2e mode) and the electron app before running. Use the `:fast` variants when iterating to skip the build step.

---

## Requirements

- The `hyperloop-control-station` electron app must be built (handled automatically by `pnpm test`).
- `testing-view` must be built in e2e mode (`build:e2e`), also handled automatically.
- Workers are set to `1` — Electron tests must run serially since only one app instance can run at a time.

> **Note:** The app runs in its normal production mode during tests — there is no special test environment or mock mode.
56 changes: 56 additions & 0 deletions e2e/fixtures/electron.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
_electron as electron,
test as base,
type ElectronApplication,
type Page,
} from "@playwright/test";
import path from "path";
import { fileURLToPath } from "url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ELECTRON_APP_PATH = path.resolve(__dirname, "../../electron-app");

type ElectronFixtures = {
app: ElectronApplication;
page: Page;
logPage: Page;
};

export const test = base.extend<ElectronFixtures>({
app: async ({}, use) => {
const app = await electron.launch({
args: ["--no-sandbox", path.join(ELECTRON_APP_PATH, "main.js")],
cwd: ELECTRON_APP_PATH,
env: {
...process.env,
NODE_ENV: "test",
},
});

// Wait for both windows to open before yielding the app fixture,
// so logPage and logWindow fixtures can safely index into app.windows()
await app.firstWindow(); // Backend Logs — always first
await app.waitForEvent("window"); // Control Station — always second

await use(app);
await app.close();
},

// Backend logs window — always opens first
logPage: async ({ app }, use) => {
const page = app.windows()[0];
await page.waitForLoadState("domcontentloaded");
await use(page);
},

// Main control station window — always opens second
// Waits for the app to reach "active" mode before yielding
page: async ({ app }, use) => {
const page = app.windows()[1];
await page.waitForLoadState("domcontentloaded");
await page.waitForSelector('[data-testid="mode-badge"]:not([data-mode="loading"])', { timeout: 15000 });
await use(page);
},
});

export { expect } from "@playwright/test";
19 changes: 19 additions & 0 deletions e2e/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "e2e",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"build": "pnpm --filter testing-view build:e2e && pnpm --filter hyperloop-control-station build:testing",
"test": "pnpm run build && playwright test",
"test:ui": "pnpm run build && playwright test tests/ui",
"test:integration": "pnpm --filter hyperloop-control-station build:testing && playwright test tests/integration",
"test:fast": "playwright test",
"test:fast:ui": "playwright test tests/ui",
"report": "playwright show-report"
},
"devDependencies": {
"@playwright/test": "^1.50.0",
"electron": "^40.1.0"
}
}
30 changes: 30 additions & 0 deletions e2e/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { defineConfig } from "@playwright/test";
import path from "path";
import { fileURLToPath } from "url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));

export default defineConfig({
testDir: "./tests",
timeout: 30_000,
retries: 0,
workers: 1, // Electron tests must run serially — only one app instance at a time

reporter: [
["list"],
["html", { outputFolder: "playwright-report", open: "never" }],
],

projects: [
{
name: "ui",
testDir: "./tests/ui",
use: {},
},
{
name: "integration",
testDir: "./tests/integration",
use: {},
},
],
});
Loading
Loading