Plugin test kits: an every-plugin "test" slot + layered consumer regression — plugins own their test-data fabrication
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 30/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- typescript
- Lĩnh vực
- backend, testing-qa
Hướng nghiên cứu
Start with definePlugin and the auth plugin’s service and test files, then read the consumer regression runner described in #368. Trace how plugin procedures are registered and how runtime route ownership selects specs. Done means the gated auth factories use real services and the acceptance criteria are met, including a citynode end-to-end regression and derived spec selection.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Problem
Consumers with browser-regression suites have no way to fabricate a remote plugin's state except by re-implementing the plugin's internals: vendor-copying its schema + migrations, building a parallel Better Auth instance with a fraction of its plugin list, and hand-inserting rows that bypass its invariants. The drift is structural — citynode's fixtures still carry a new_member column and pre-rc.7 stats semantics and produce deterministic red specs (NEARBuilders/citynode.app#426), while its parallel instance is why an approve-test-organizations script must undo what the real plugin's approval flow does. Meanwhile, children re-testing plugin behavior deeply is the only net catching upstream regressions today — late, duplicated in every child.
Precedents
- better-auth's
testUtils()— a plugin exposing test endpoints when mounted. The auth plugin's kit will use it internally (behind this seam) to implementmintSession; this ask generalizes the pattern to every plugin with the host owning the gate. - Package-owned factories (Rails engine fixtures, Laravel
HasFactory, WordPress factories) — the domain ships its fixtures; consumers never re-implement invariants. - Env-gated dev surfaces inert in production (devtools NoOp builds) — inert by registration, not authorization.
- Derived test selection (Nx "affected") — spec applicability computed from an ownership graph, not hand-curated.
Proposal
One word at every layer of the seam — the slot, the RPC namespace, and the manifest key are the same word, so they cannot drift apart:
| Layer | Name |
|---|---|
definePlugin slot |
test |
| Consumption | apiClient.<plugin>.test.<factory> |
| Manifest | "test": true |
| Env gate | BOS_TEST_MODE=1 |
| Harness adapter (host side) | everything-dev/test-kit |
Ownership split (mirrors how migrations already split): slot + gating + plumbing → every-plugin; factories → each plugin (ordinary plugin code, like db/migrate.ts adapters); harness/runner → everything-dev/test-kit.
The slot — factories return Effects, call the plugin's real services with a time seam, and are state-named (the name promises the aggregate state, not the transition — the previous drift was exactly a transition/state mismatch):
test: ({ services, db, config }) => ({
mintSession: (i: { role?; organizationId? }) => Effect<Session, KitError>,
approvedOrganization: (i: { name }) => Effect<Organization, KitError>,
verifiedEmail: (userId) => Effect<void, KitError>,
createOnboardingCode: (i: { organizationId; expiresAt: Date; maxUses?: number }) =>
Effect<{ code; codeId }, KitError>,
joinsThisMonth: (i: { organizationId; redeemed: number; newMembers: number }) =>
Effect<Stats, KitError>,
})
Cookie mechanics stay behind the seam: the RPC adapter sets the session cookie on the response (as better-auth does); the in-process adapter returns the session handle. Consumers never learn what a cookie is — which also deletes the child's cookie-artifact pipeline rather than relocating it.
Seeded state is valid by construction — there is no parallel re-implementation to drift.
Gating: the host registers test/* plugin procedures only under BOS_TEST_MODE=1; they never enter the production router (registration-gated, devtools-style).
The layers
- L0 — plugin tests (upstream): kit consumed in-process.
- L1 — the framework browser suite gates the release train: upstream accidents die here, before publish.
- L1.5 —
consumer-regression.yml(#368): re-runs a runtime-map-derived selection of framework specs against a child's composition. Route ownership (from the manifest/composed route tree) decides applicability — a child that shadows/loginreplaces the framework's/loginspecs with its own. Derived, not curated, so the selection can't drift. - L2 — children shrink to: thin contract smoke, child behavior (their overrides), child flows (kit-fabricated data). The parallel instance, vendored fixtures, raw inserts, and cookie-artifact pipelines are deleted.
First implementation
The auth plugin ships the starter surface above. A consumer's spec becomes:
const { code } = await apiClient.auth.test.createOnboardingCode({ organizationId, expiresAt });
…and tests/regression/fixtures/auth/, auth-test-instance.ts, approve-test-organizations.ts, verify-test-emails.ts, and the migrate-runner mirror in citynode all become unnecessary.
Acceptance criteria
-
definePluginaccepts atestslot; procedures are registered only underBOS_TEST_MODE=1; a boot warning fires if the gate is set in a production-shaped environment. - The manifest advertises
"test": true;boscan list a runtime's available test surfaces. - Auth plugin implements the starter surface with factories calling its real services.
- A consumer (citynode) seeds auth state end-to-end via gated RPC with no vendored schema/migrations, no parallel instance, and no raw auth-DB inserts.
- Session fabrication sets cookies on the response — no cookie-artifact interchange in the child.
- consumer-regression (#368) derives its spec selection from route ownership.
- Documented convention so each new plugin ships its
testsurface by default.
Cross-refs
#368 (consumer-regression runner), #531 (session wall — related non-gating cause), NEARBuilders/citynode.app#426 (motivating failure), #582/#583 (child UX asks this doesn't cover).
- Ngôn ngữ chính
- TypeScript
- Star
- 5
- Fork
- 3
- Merge trung bình
- 9 giờ 35 phút
- Pull request đã merge (30 ngày)
- 151
Chuẩn bị môi trường
- Có Dockerfile hoặc tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của NEARBuilders/everything-dev
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 77/100
NEARBuilders/everything-dev#628 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
NEARBuilders/everything-dev#400 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
NEARBuilders/everything-dev#632 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Pinnable dev host slot for child CI — versioned host bundle URLs or a first-class local-host runnerĐang mởenhancement ready-for-agent
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
NEARBuilders/everything-dev#613 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
documentation ready-for-agent
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 66/100
NEARBuilders/everything-dev#608 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của NEARBuilders/everything-dev
Issue tương tự
-
bug needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
apex-dev-tools/apex-log-parser#199 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area/frontend/library-panels automated-triage type/bug type/ux
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
PostHog/posthog.com#21607 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 73/100
ajv-validator/ajv#2689 ·
-
[Bug]: IME confirmation Enter can submit the SSH port-forward dialogCó thể đã có người làm @seijikohara đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
Maintainer thường phản hồi trong vòng 1 ngày