Skip to content

finding(test-infra): importOriginal() on the source-aliased @object-ui/app-shell barrel costs ~10s per console test file — measured once, and up to 12 files are in the same shape #6580

Description

@os-support-ai

Surfaced while implementing #6567 (PR #6579). That card fixed one file; this is the property of the tree that produced it, which the fix deliberately did not touch.

The mechanism, measured

In apps/console, the @object-ui/app-shell specifier is aliased to source, not to built output:

apps/console/vite.config.ts:472
'@object-ui/app-shell': path.resolve(import.meta.dirname, '../../packages/app-shell/src'),

packages/app-shell/src/index.ts is 385 lines and carries 8 bare side-effect imports (:277, :279, :280, :281, :283, :286, :289, :292builtinComponents, CloudConnectionPanel, InstalledListWidget, ConnectAgentWidget, CloudOnboardingNext, CloudAiModelStatus, record-attachments-renderer, record-approvals-renderer). All three of those numbers were re-measured on main independently of the PR that reports them.

So a test file that mocks the package with a factory taking importOriginal

vi.mock('@object-ui/app-shell',async(importOriginal)=>{constactual=awaitimportOriginal<Record<string,unknown>>();});

— makes its first value request for that package transform that whole graph on demand. Instrumented on an idle machine in #6567: importOriginal(app-shell) = 10204 ms of a 10223 ms total import, i.e. 99.8%. For comparison, auth in the same file was 240 ms and the render plus assertions were ~12 ms.

Why it is worth a card beyond the file that was fixed

In #6567 that 10.2 s happened to land inside a test case's testTimeout window, because the module was reached by an await import() in the case body. The case then failed whenever the transform pipeline was saturated by a full-project run — a flake whose cause was neither of the two suspects the card named. #6579 fixed it by moving the load to module scope, i.e. out of the bounded window into the import phase that nothing bounds.

That fix is correct and it is not what this card asks to revisit. The point is that the 10.2 s is still spent, on every file in this shape, and any file that reaches the package from inside a bounded window is a latent repeat of the same flake.

The suite-level numbers are consistent with this not being rare. Three green full-project apps/console runs on the fixed tree reported setup times of 555 s, 721 s and 840 s against durations of 252 s, 323 s and 373 s.

Population — an upper bound, stated as one

GitHub code search over this repo:

  • files containing vi.mock('@object-ui/app-shell'21
  • files under apps/console containing importOriginal16
  • intersection — 12
apps/console/src/components/FormPage.predicateScope.test.tsx <- the one already fixed
apps/console/src/components/SetupRoute.test.tsx
apps/console/src/components/StudioRoute.test.tsx
apps/console/src/pages/system/ApprovalsInboxPage.cellIdentity.test.tsx
apps/console/src/pages/system/ApprovalsInboxPage.hiddenFieldTrim.test.tsx
apps/console/src/pages/system/ApprovalsInboxPage.queueHiddenAmount.test.tsx
apps/console/src/pages/system/ApprovalsInboxPage.rawPayloadGate.test.tsx
apps/console/src/pages/system/ApprovalsInboxPage.recordLink.test.tsx
apps/console/src/pages/system/ApprovalsInboxPage.stepProgressVertical.test.tsx
apps/console/src/pages/system/__tests__/AppManagementPage.i18n.test.tsx
apps/console/src/pages/system/__tests__/AppManagementPage.mutations.test.tsx
apps/console/src/pages/system/__tests__/AppManagementPage.search.test.tsx

⚠️12 is an upper bound, not a count, and the reason is worth stating so nobody quotes it as measured: the intersection is computed from file paths, so a file lands in it if it mocks app-shell and uses importOriginal somewhere — but that importOriginal may belong to a different mocked module (react-router-dom and similar are mocked the same way). Confirming the real number needs a per-file read of which factory the importOriginal sits in. A further 9 files mock the package with no importOriginal anywhere in them and are therefore not affected by this mechanism.

Second caveat: GitHub code search is an index and can lag or be incomplete, so these are lower bounds on the populations themselves.

Not a request to weaken anything

Explicitly not asking to raise a timeout, to add files to heavyDomTests, or to skip or quarantine anything — those were all available in #6567 and all correctly declined. The levers that would actually change this are upstream of any gate: whether the test alias should resolve to built output rather than source, whether the barrel's 8 side-effect imports need to be in the module graph an importOriginal() pulls, or whether the mock factories should avoid importOriginal for this package. Choosing among those is a sizing question, not this card's to answer.

Filing note

Filed unassigned and ungraded by the domain:ui execution seat (session session_011SfZeFWrhGLHmfq61xbz4q). It lands in console test configuration rather than in a shipped package, so the routing label and the grade are triage's to produce. Duplicate check before filing found no open card of this shape.

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repopm:queue

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions