FForm Platform
enzh-CN

Testing and quality

Use layered automated testing and deployment gates to keep a configurable platform safe to evolve.

FormPlatform Testing Guide

中文:TESTING_GUIDE.zh-CN.md

1. Current test architecture

FormPlatform uses layered verification:

LayerLocationPurposeDependencies
Frontend unit/contracts`src/FormPlatform.Host/ClientApp/src/**/*.test.js`pure runtime rules, public component contracts, regressionsNode.js, Vitest
Static checksprojects/scriptsJSON/XML/JS/C# structure, links, formatting, manifestsnone/local SDK
PostgreSQL integration`tests/FormPlatform.PostgreSql.Tests`real ORM, transaction, reference, migration/checksum behaviorDocker
SQL Server integration`tests/FormPlatform.SqlServer.Tests`real SQL Server ORM, generated-key/paging, migration/checksum behaviorDocker
Playwright E2E`tests/e2e`browser, auth, routing, forms, modules, error UXrunning Host, Chromium, test account
All-module build`eng/build-all.ps1`Host/SDK/Sample/Todo/ResourceBooking compatibilityNode, .NET, sibling repositories
Manual acceptancebrowser/database/logsDesigner, printing, payment/OIDC, environment flowstarget environment

GitHub CI now enforces seven gates: frontend Vitest, build and stage every module, SDK/module compatibility, PostgreSQL Testcontainers, SQL Server Testcontainers, the real Host against isolated PostgreSQL for Playwright, and a final release-runtime integrity gate. The final gate depends on every earlier gate.

2. Prerequisites

Use .NET 10 SDK and Node.js 22. PostgreSQL tests require Docker. E2E requires a separately running FormPlatform, and ResourceBooking tests require that module and client extension.

Never point automation at development or production data. Testcontainers creates a temporary PostgreSQL. The E2E Host also needs a dedicated database and secrets.

3. PostgreSQL integration tests

dotnet test tests/FormPlatform.PostgreSql.Tests/FormPlatform.PostgreSql.Tests.csproj -c Release

`PostgreSqlFixture` starts `postgres:17-alpine` and implements `IDatabaseConnectionFactory`. Tests in the xUnit collection share a container, so isolate with unique rows/tables or cleanup.

Current coverage includes dynamic repository/provider behavior and migration once-only/checksum/Core-Commerce schema behavior.

3.1 Add ORM tests

Use real metadata, repository, dialect, and UnitOfWork rather than mocked SQL. Project explicit fields and assert that unrequested attributes are absent. Use unique IDs/names and never rely on test order.

3.2 SQL Server integration tests

dotnet test tests/FormPlatform.SqlServer.Tests/FormPlatform.SqlServer.Tests.csproj -c Release

`SqlServerFixture` starts an isolated SQL Server 2022 container. It verifies the SQL Server dialect's CRUD/filter/offset-paging/generated-key path and applies the complete Core and Commerce migration chain twice, including checksum protection. This is deliberately independent from a locally installed SQL Server.

3.3 Add migration tests

Verify empty-database execution, idempotent second execution, history module/id/checksum, checksum mismatch failure, and a new migration following old history. PostgreSQL is currently automated; MySQL and SQL Server still need provider CI or pre-release environment tests.

3.4 Testcontainers troubleshooting

Run `docker info`; inspect proxy/registry settings for image failures; allow first-run download time; avoid fixed port 5432; and prevent collisions because the fixture shares one container.

4. Release runtime integrity gate

After every earlier CI gate passes, the staged runtime is checked by `eng/validate-release-runtime.ps1`:

  • Host, SDK, contracts, appsettings, SPA asset references, module manifests, and module entry assemblies must exist.
  • `appsettings.json` must not contain non-empty connection strings, passwords, secrets, encryption keys, API keys, or private keys. Deployment secrets belong in environment variables, User Secrets, or the external deployment secrets document.
  • `DataAccess:IncludeSqlParameterValues` must remain `false`.
  • The existing binary module validator runs again, and `release-manifest.json` records SHA-256 hashes for every delivered file.

Run the same gate after `eng/prepare-ci-runtime.ps1` before manually publishing an artifact:

./eng/validate-release-runtime.ps1 -RuntimeDirectory .ci/runtime -WriteManifest

The resulting `formplatform-release-candidate` CI artifact is a tested, integrity-listed candidate; release approval should require the `release-readiness` job in branch protection.

5. Playwright E2E

cd tests/e2e
npm install --no-audit --no-fund
npm run install:browsers

Prepare a dedicated Host/database, apply migrations, create a role-appropriate test user, deploy tested modules, build the client, and start the Host.

$env:FORMPLATFORM_E2E_BASE_URL='http://localhost:5080'
$env:FORMPLATFORM_E2E_USER='e2e-admin'
$env:FORMPLATFORM_E2E_PASSWORD='use-a-secret-value'
cd tests/e2e
npm test

Debug with `npm run test:ui`, `npx playwright test specs/core.spec.js --headed --debug`, and `npx playwright show-trace ...`.

Current core flows cover public standalone Designer, validated client-extension discovery, authenticated Form Center, direct/refresh module routing, and preserving a mounted form after a server 409. Login tests may skip locally when credentials are absent, but missing CI credentials fail the run.

5.1 Stable E2E rules

Prefer roles, labels, and test IDs over Tailwind classes or DOM hierarchy. Mock only a boundary outside the test objective. A 409 route mock is valid for error UX; it is invalid for a real persistence test. Each test creates/cleans its own data.

Critical coverage includes Designer/Preview/Viewer, all identity modes, CRUD/failure preservation, pagination draft/final state, boolean/hidden fields, DataGrid editing/sort/export, AsyncSelect/Tree references, module direct routes, i18n/toasts/field errors, print exclusion, and Survey upload/download authorization.

6. All-module build

Expected layout:

workspace/FormPlatform
workspace/Todo
workspace/ResourceBooking

Run:

./eng/build-all.ps1 -Configuration Release

The script builds ClientApp, Host/SDK, Sample, Todo, and ResourceBooking client/server. Missing modules/manifests fail instead of being skipped. `-SkipClientBuild` provides a faster server compatibility check; path parameters can override sibling locations.

GitHub variables are `FORMPLATFORM_TODO_REPOSITORY` and `FORMPLATFORM_RESOURCE_BOOKING_REPOSITORY`; private repositories use a read-only `FORMPLATFORM_MODULES_TOKEN`.

`eng/prepare-ci-runtime.ps1` stages the Host, Vue assets, Sample, Todo, and ResourceBooking under `.ci/runtime`. Then run:

./eng/validate-module-compatibility.ps1 -RuntimeDirectory .ci/runtime

The Host's `--validate-modules` mode loads the real packages and validates manifest schema/name, module/assembly version equality, SDK/Platform ranges, SDK reference compatibility, and absence of obsolete Host references. It neither connects to a database nor starts HTTP. Playwright uses a `postgres:17-alpine` service and saves Host logs, reports, traces, and screenshots; PostgreSQL tests save TRX results. Require all four jobs in branch protection.

7. Client unit, contract, and static testing

ClientApp uses Vitest for substitutions, Action Context isolation, validation/cache/debounce, Pagination, Checkbox/Radio, DataGrid models, and exhaustive built-in contracts:

cd src/FormPlatform.Host/ClientApp
npm run test:unit
npm run test:unit:watch

See Client Component Contracts. Unit tests protect pure/runtime rules; Playwright remains preferred for real control interaction. The production build validates Vue templates, dynamic imports, and bundling.

Static checks include `node --check` for plain JS, JSON/XML parsing, `git diff --check`, Markdown relative-link checking, and manifest version/schema checking. Vue SFCs require Vite or a Vue parser; `node --check` is insufficient.

8. API/error contract tests

Assert status, problem content type, and stable fields: `code`, `messageKey`, `fallback`, `fieldErrors`, `status`, and `traceId`. A 500 must not reveal SQL, connection strings, secrets, or stack traces. Empty 401/403/404 responses should receive the same platform envelope. Client tests ensure field errors remain attached to the active editor/FormReader.

9. Manual acceptance

Environment-dependent checks remain necessary for OIDC callbacks, SMTP, PayPal/Stripe/WeChat sandboxes, print/PDF, browser local date/time, IIS/Nginx forwarding, large files, production database permissions, and backup/restore.

Minimum release smoke: clean startup with no migration/module errors, login/logout, Form Center, Designer, create/update a regular record, submit one Survey, query a DataGrid, open a module route, and inspect logs for unhandled failures.

10. Test data and security

Credentials for shared or persistent test environments are CI secrets, not spec literals. The fixed password in the E2E workflow belongs only to its per-job disposable database and must never be reused. Do not use personal data. Use payment/OIDC sandboxes. Failure traces may contain form content, so limit artifact access and retention. Keep sensitive SQL parameter logging disabled.

11. Strategy template

For each feature decide whether it needs a unit rule test, PostgreSQL integration, migration history test, API contract assertion, Playwright interaction, provider-specific migration run, allow/deny matrix, or external-service/manual smoke. A bug fix starts with a reproducer; after it passes, remove obsolete workarounds.

12. Recommended CI stages

1. Frontend Vitest and component contracts.

2. Client production build plus Host/SDK/all-module build.

3. Stage the deployable runtime and validate every SDK/module package through the Host.

4. PostgreSQL integration.

5. Isolated PostgreSQL/Host plus Playwright core.

6. Preserve runtime, TRX, Host log, and failure traces.

7. SQL Server migration/ORM Testcontainers suite.

8. Release runtime integrity gate and SHA-256 manifest.

9. Staging external-service smoke, then production approval.

Preserve the earliest root-cause log. A successful build alone does not prove migrations, module loading, or browser flows.