Tests

A package can ship unit tests (vitest) and end-to-end tests (Playwright). Each member carries its own vitest.config.ts and playwright.config.ts that inherit the app shell’s canonical config, and the tinycld-pkg CLI runs them - scoped to one member, or across every present member with --all. You don’t need to wire global config; place files in the right location and follow 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 specs live under tests/e2e/ and end in .spec.ts:

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

Declare the directory in the manifest:

tests: { directory: 'tests' },

How discovery works

Each member ships two small config files that defer to the app shell’s canonical setup:

The tinycld-pkg CLI runs the right config for whichever member you’re in:

# from any member directory
pnpm exec tinycld-pkg test       # vitest for this member
pnpm exec tinycld-pkg test:e2e   # playwright for this member
pnpm exec tinycld-pkg check      # typecheck + unit for this member

From anywhere, add --all to run across every present member:

pnpm exec tinycld-pkg test --all
pnpm exec tinycld-pkg test:e2e --all
pnpm exec tinycld-pkg check --all

The app shell also exposes pnpm run test, pnpm run test:e2e, and pnpm run check (single member = the app), plus pkg:test:unit / pkg:check / pkg:test:e2e wrappers that run --all.

What you can import

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

Use the app shell’s test helpers (@tinycld/core test helpers, Playwright page objects under the app’s 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 a present member and has a screen at tinycld/example/screens/index.tsx.

Tests for packages that aren’t present

tinycld-pkg <verb> --all only runs the members that are present in the workspace. A feature that isn’t cloned in simply contributes no tests - cloning or removing a member flips its tests in and out of the run with no config changes on your part.