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
- Vitest (
tinycld/vitest.config.ts) globspackages/*/tests/**/*.test.tsandpackages/@*/*/tests/**/*.test.ts, with an override that stops the defaultnode_modulesexclude from masking the symlinked siblings. - Playwright (
tinycld/playwright.config.ts) uses the same glob pattern for*.spec.ts.
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:
~/...resolves to the app shell’s root. Import~/lib/...,~/tests/unit.helpers.tsx, etc.@tinycld/core/...resolves to the bundled core library. Import@tinycld/core/lib/pocketbase,@tinycld/core/ui/form, etc.@tinycld/<other-pkg>/...resolves to a linked feature sibling - useful only if your package legitimately depends on another (it usually shouldn’t).- Relative imports resolve within your package.
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.