Skip to content

v16.0 browser test checklist — exercise every 16.0 feature in the running app #3358

Description

@os-zhuang

Centralized browser-based verification of the entire 16.0 release. Each item is a shipped 16.0 capability with a concrete path to exercise it and the expected result. Source of truth: content/docs/releases/v16.mdx (PRs #3322 / #3331 / #3357).

Environment

  • Boot the showcase / CRM example app and drive it in a browser as admin + a regular user (see the dogfood-verification skill). Showcase seeds make most features demonstrable out of the box.
  • Legend: 🖥️ = verify in the Console/Studio browser UI · 🔌 = backend/API/CLI — not directly browser-driven, verify via REST/os CLI or an API panel · ⚠️ = a fix that is easiest to confirm by reproducing the old broken behavior.

1. Approvals 🖥️

  • M-of-N quorum — configure an approval step with quorum + minApprovals; submit; confirm it approves once the threshold is met, and that a single rejection still vetoes.
  • Per-group sign-off (会签) — configure per_group with 2 named groups (e.g. manager + finance); confirm it needs one approver from each group; try the showcase ExpenseSignoffFlow.
  • Server-computed progress — a pending multi-approver request shows per-group tick badges / “2 of 3 · finance pending”, not a client guess.
  • Decision attachments — on approve/reject, attach a file through the decision dialog; confirm it uploads and shows as a named chip in the timeline.
  • Notification deep link — click an approval bell notification; confirm ?request=<id> opens the request drawer directly.
  • Metadata-driven inbox actions — the inbox renders approve / reject / reassign / send-back / request-info / remind / recall / resubmit from declared actions (no hand-wired buttons); each executes its REST route.
  • Viewer gating — as the submitter viewing your own pending request: you do not see approver buttons; as a position-addressed approver: you do see them (not hidden by a client heuristic).
  • Reassign user picker — the reassign dialog renders a real sys_user picker (not a free-text id box).

2. Automation / Flow (Studio) 🖥️

  • Time-relative trigger — author a flow start node with timeRelative (offsetDays: [60,30,7] or withinDays); confirm the first-class designer panel; verify it fires per matching record on the daily sweep.
  • Nested regions on the canvas — a loop/parallel/try_catch node shows its nested region inline (not an opaque card); select and edit a node inside a region through the schema-driven inspector.
  • Flow Runs step logs — run a flow with a loop; the Runs panel nests per-iteration / per-region steps.
  • Schema-driven keyValue / numberList — a node with a free-form {var:value} map renders a keyValue editor (not raw JSON); a number array renders numberList.
  • Roll-up summary filter editor — edit a summary field; set a child-row filter via the visual editor; confirm the parent total only counts matching children.
  • 🔌 Flow observability banner — on os dev/serve, a misauthored auto-launched flow surfaces lines in the Flows: startup banner and ERROR logs on a failed trigger run.

3. Dashboards & Analytics 🖥️

  • Dataset-only widget authoring — the widget config panel is a dataset picker (chart and pivot); the inspector emits only dataset + dimensions + values.
  • ⚠️ Strict dashboard widgets — author a widget with a stray/legacy key (e.g. categoryField); confirm a loud parse error naming the key + pointing at the dataset shape (was: silently renders nothing).
  • Report drill-through range — drill a date-bucket cell (e.g. “2026-Q2”); confirm the drilled list is scoped to that exact time range, not a superset.
  • ⚠️ Chart first paint — a dashboard with bar charts draws bars on first paint (no blank-until-resize).

4. Records / Lists / Detail / Forms 🖥️

  • Action param real widgets — an action with file/image/richtext/color/date params renders each real widget in the dialog (not a text input); file params upload via the ambient provider (multiple/accept/maxSize).
  • ⚠️ Upload guard + autonumber — Confirm is disabled while a file/image param is still uploading; a spec autonumber param maps to the AutoNumber widget.
  • Option-widget visibleWhen parity — a dependent select/multiselect/radio/checkboxes option shows/hides as its parent changes (cascading + dependsOn); select + multiple renders a multi-value chip picker.
  • Master-detail atomic save — save a master + line items in one go; confirm one atomic batch (no partial writes on failure).
  • Related lists pagination — a record with many children paginates via server $top/$skip (doesn’t load every row).
  • Record History tab — shows display values, not raw audit payloads; no phantom “value → null” rows for computed fields.
  • Inline edit — double-click a field, edit several (incl. header highlights), save once atomically; computed/readonly fields stay non-editable.
  • List polish — toolbar manual refresh button; injected owner_id stays out of leading columns and lands in the detail meta section.
  • ⚠️ Import wizard — a disabled Next explains itself (unmapped required fields hint); GBK/GB18030 zh-CN CSV imports without garbled headers; legacy per-row fallback shows a “compatibility fallback” notice.
  • Single-file child grid — a child object with one file field stays an inline grid (doesn’t flip to a per-row form).

5. Access / Studio pillar 🖥️

  • Permission matrix hits first screen (B1) — identity + zero-grant capability sections start collapsed.
  • Explain panel object dropdown (B2) — object field is a package-scoped dropdown, not free text.
  • Field-level bulk + filter (B4) — a wide object gets a field filter + Read-all/Write-all/Clear over visible rows; Bulk column not clipped at narrow widths (B3).
  • Record-grained AccessExplainPanel — pick user+object+record; see per-layer attribution (permission set → position → sharing → row rules) + a record.visible verdict with the deciding layer.
  • Provenance / bucket badges — platform/package/admin provenance badges; writable-system objects distinguished from engine-owned in badges + empty states.
  • Read-only package locks matrix — on a read-only package the matrix checkboxes/Save are actually disabled.

6. Auth / Login / Identity 🖥️

  • ⚠️ SSO-only not stranded — on a cold-started env, the login page honors ssoEnforced on first paint (no password wall flash); a hung sign-in recovers via watchdog.
  • Dev admin hintos dev login page shows the dev-seeded admin credential hint.
  • Import wizard auto policy — the user-import wizard defaults to Automatic (recommended); reachable rows are invited, unreachable get a one-time password shown once.
  • Phone sign-in surfaces — create a phone-based user; the phone number shows in the create result dialog, the All Users list, and the record detail highlights.

7. i18n 🖥️

  • ⚠️ Notifications actually clear — on a zh-CN workspace, a collab.assignment bell notification title is localized (recipient locale), opens a localized detail page, and mark-as-read clears the unread state on standalone/os dev (the notifications REST routes are now mounted).
  • Action result dialog localized — create a user on a translated locale; the temporary-password result dialog (title/description/acknowledge/field labels) is translated, not hardcoded English.
  • Storage objects localizedsys_file detail page labels + the Pending/Committed/Deleted status pipeline render in the workspace locale.
  • Studio follows in-app locale — switch the in-app locale; Studio/metadata-admin follow it (no mixed-language session); relative dates localize.

8. Gantt (plugin-gantt) 🖥️

  • Ownership-aware reschedule — drag/auto-schedule an own-dates summary; it carries its unlocked subtree; locked tasks are reported, not moved; toolbar auto-schedule confirms first (“shift N tasks? (M locked skipped)”).
  • Manual scheduling + veto — manual-scheduling summary bars; a beforeTaskUpdate host veto blocks a bad drag; dependencyTypes switch hidden for id-only stores.
  • Removed — the mobile QR-share context action is gone.

9. Backend / API / CLI (indirect) 🔌

  • organizationId in hooks/actionsctx.user.organizationId / ctx.session.organizationId resolve; tenantId alias removed.
  • MCP stdio API-key — stdio auto-start without OS_MCP_STDIO_API_KEY fails closed; with a valid key, reads honor RLS/FLS.
  • transactionalBatch discovery bitclient.capabilities.transactionalBatch reflects whether /batch is mounted + transaction-capable.
  • ⚠️ Write-path guardsreadonly fields stripped on INSERT+UPDATE via REST; owner_id forge/transfer denied; cross-object /batch gated by per-object API rules; bulk-update runs validation rules.
  • ⚠️ Formula fixesrecord.due_date == today() matches; cond ? x : null + floor/ceil work; date arithmetic (end - start + 1) is now a build-time error in os build.
  • ⚠️ checkboxes per-option visibleWhen enforced server-side — a crafted write of a gated checkboxes option is rejected.
  • enforce-or-remove sweep — authoring a removed field/object key, a dead hook event, events:['delete'], a webhook undelete/api trigger, or aiStudio/aiSeat fails at parse/build.
  • Server-Timing — with OS_SERVER_TIMING / X-OS-Debug-Timing, an admin sees auth/db/hooks/serialize spans; a non-admin does not.
  • MCP validate_expression — an agent validating a formula against an object schema gets errors/warnings/inferred type.

Notes

  • Track findings by checking boxes; file a linked bug per failure with repro steps + the responsible PR/ADR from v16.mdx.
  • ⚠️ items are regressions/holes fixed in 16.0 — the strongest test is to reproduce the old broken behavior and confirm it no longer happens.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions