Tests

A package can ship unit tests (vitest) and end-to-end tests (Playwright). The app shell’s test runners are already configured to discover them; you don’t need to wire anything up beyond placing files in the right location and following the naming conventions below.

Directory and naming

Put tests under a tests/ folder at the root of the package. Unit tests end in .test.ts; e2e tests end in .spec.ts:

example/
    tests/
        manifest.test.ts
        example.spec.ts

Declare the directory in the manifest so Playwright config knows where to look:

tests: { directory: 'tests' },

The manifest field is specifically for Playwright discovery. Vitest picks up unit tests without any manifest declaration - it globs linked siblings by path.

How discovery works

Run everything from the app shell:

npm run test:unit     # vitest - includes all linked siblings
npm run test:e2e      # playwright - includes all linked siblings

Filtering by path works the same as for app-shell tests:

npm run test:unit packages/@tinycld/contacts
npm run test:e2e --grep "contacts"

What you can import

Package tests run inside the app shell’s resolver context, so the same aliases work:

Use the app shell’s test helpers (~/tests/unit.helpers.tsx, Playwright page objects under ~/tests/) rather than reinventing fixtures. If a helper you need doesn’t exist yet and is broadly reusable, it belongs in @tinycld/core; package-specific helpers belong in the package.

A minimal e2e spec

import { test, expect } from '@playwright/test'

test.describe('Example', () => {
    test('list screen renders', async ({ page }) => {
        await page.goto('/a/test-org/example')
        await expect(page.getByText('Example')).toBeVisible()
    })
})

Playwright boots the app shell against the seeded dev org, so the URL above works if the package is linked and has a screen at screens/index.tsx.

When tests run against packages that aren’t linked

If the test runner is pointed at tests/ folders in siblings that aren’t listed in tinycld.packages.ts, those tests simply don’t execute - the app shell only globs inside packages/ (the symlinked tree), and unlinked siblings have no symlink. Linking and unlinking a package flips its tests in and out of the run with no config changes on your part.