TMA CloudTMA Cloud
GuidesOperations

Testing

Running the TMA Cloud test suites.

Running the TMA Cloud test suites.

Overview

There are five suites, all using Vitest. Three run from a clean checkout with no services; two talk to real infrastructure.

SuiteLocationNeeds
Backend unitbackend/tests/unit, backend/tests/integrationNothing
Backend integrationbackend/tests/integration-dbPostgreSQL and Redis
S3 storage driverbackend/tests/integration-s3An S3-compatible bucket
Frontendfrontend/testsNothing
Desktop appelectron/testsNothing

backend/tests/integration holds route-level tests that mount the real routers with the controllers stubbed. They need no services, so they run as part of the unit suite.

Backend Commands

Run from the backend directory.

Unit Tests

npm test

Run the unit and route-level suites once. Exits non-zero on failure.

npm run test:watch

Re-run affected tests as files change.

npm run test:coverage

Write a coverage report to backend/coverage.

Integration Tests

npm run test:integration

Run the suite that uses PostgreSQL and Redis. See Integration Setup first.

npm run test:integration:coverage

Same, with a coverage report in backend/coverage-integration.

S3 Tests

npm run test:s3

Exercise the storage driver against the bucket configured in .env. Requires bucket credentials to be set.

Everything

npm run test:all

Run the unit suite, then the integration suite.

Frontend Commands

Run from the frontend directory.

npm test

Run the frontend suite once.

npm run test:watch

Re-run affected tests as files change.

npm run test:coverage

Write a coverage report to frontend/coverage.

Test files are type-checked by their own TypeScript project:

npx tsc -b tsconfig.test.json

Desktop App Commands

Run from the electron directory.

npm test

Run the desktop app suite once.

npm run test:watch

Re-run affected tests as files change.

npm run test:coverage

Write a coverage report to electron/coverage.

The suite runs under plain Node with no Electron runtime: require('electron') is redirected to an in-memory double, and child_process.spawn and net.createServer are replaced per test so PowerShell never runs and no named pipe is bound. Nothing is mounted, no window opens, and it runs the same on Windows and on the Linux CI runner.

Integration Setup

The integration suite reads connection details from the project .env, then overrides database and cache settings and replaces bucket storage with an in-memory double so it never touches working data. Setup fails with an error if an override has not taken effect.

OverrideReason
DB_NAME=tma_cloud_testIts own database. Setup stops unless the name ends in _test.
REDIS_DB=15Its own cache. Setup stops if the value is 0.

Bucket operations use an isolated in-memory double in this suite. Run npm run test:s3 separately to verify the actual provider.

Create the database once:

createdb tma_cloud_test

Migrations run against it on the first test run, so the schema matches production. Each test starts from a truncated database, an empty in-memory bucket, and a flushed cache.

The S3 suite writes every object under a tma-test/<run-id>/ prefix and deletes the prefix objects in a multi-object request when the run finishes.

What the Suites Cover

Unit

Validation and path handling, AES-256-GCM encryption, MIME detection from magic bytes, Redis caching, JWT handling, the auth and permission middleware, error-to-status mapping, and the rate limiters. Database and Redis are replaced with in-memory doubles.

Integration

The whole request path with nothing stubbed: real routers, real middleware, real controllers and models, against PostgreSQL and Redis.

  • Signup, login, sessions, revocation, CSRF
  • Upload, download, rename, move, copy, trash, restore, permanent delete
  • Sub-user permissions and the account boundary
  • Share links, expiry, and anonymous access
  • Storage quotas across an account
  • Trash retention and the 15-day cleanup job
  • Password change, its re-authentication gate, and session invalidation

S3

Single-request and unknown-length multipart uploads, full and ranged reads, atomic and multipart copies, single and multi-object deletion, stat, pagination, and encryption round trips against the configured bucket. Run it once for each supported provider configuration, including R2, because the main integration suite uses an in-memory storage double.

Frontend

API client and error handling, storage and file-name helpers, the Electron bridge, React hooks, and the Modal, Toast, and PermissionChecklist components.

Desktop App

The main process end of every desktop feature:

  • Window security — context isolation, sandbox, blocked navigation and window.open, denied permission requests, and the desktop-client header that only ever goes to the configured server origin
  • The preload bridge: which channels it exposes, and that it never hands the page a generic way to reach the main process
  • Open on desktop — download, watch, throttled re-upload, exported "Save As" files, and the size-based reuse of an already downloaded copy
  • Clipboard — the file-drop, OLE and text-as-paths sources, size caps, name sanitising, and origin checks on server-side copies
  • Cloud Drive — the per-session bridge token and that it reaches the host on stdin, the staging-directory confinement on every path the filesystem host sends, save-only mode, mount and unmount, and mounting from the auth cookie without unmounting on a token refresh
  • Updates — the installer URL, Content-Disposition filename sanitising, download progress, and launching the installer
  • Save and bulk save dialogs, temp-directory cleanup, single-instance behaviour, and the packaging contract the build scripts depend on

Continuous Integration

.github/workflows/test.yml runs lint, format check, and every suite on each push and pull request. The integration job starts PostgreSQL and Redis service containers, so it does not need shared infrastructure.

On this page