Skip to content

test: fix component-test harness dual React instance (35 -> 9 failures) - #588

Merged
agegr merged 2 commits into
agegr:mainfrom
Nuctori:fix/test-harness-react-instance
Aug 25, 2026
Merged

test: fix component-test harness dual React instance (35 -> 9 failures)#588
agegr merged 2 commits into
agegr:mainfrom
Nuctori:fix/test-harness-react-instance

Conversation

@Nuctori

@Nuctori Nuctori commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the component-test harness so React component tests actually run. This is the harness half of #586 (the other half — adding CI — is still wanted).

Every component test that renders with renderToStaticMarkup(<I18nProvider>…) was failing with useI18n must be used inside I18nProvider, even though the provider was wrapped correctly. Root cause: the test entry imported React natively (import React from "react") while jiti loaded the .tsx tree, so two React instances and two I18nContext modules existed; useContext returned null. The useI18n import also used a .tsx suffix that jiti resolved to a different module cache entry than the components' @/hooks/useI18n, producing a second distinct I18nContext.

Changed

  • components/{MermaidBlock,ChatInput,ExtensionStatusBar,ExtensionWidgets,MessageView,TurnWrittenFiles}.test.mjs: load react, react-dom/server, and I18nProvider through the same jiti instance the components use, and import useI18n via the @/ alias (matching component imports) so I18nContext resolves to one module instance. No product code touched.

Verification

  • npm test: 603 tests, 591 pass, 9 fail (was 565/35 before this fix on the same branch, 565/35 on a clean main baseline).
  • Remaining 9 failures are not harness defects: lib/directory-browser (symlink EPERM on Windows, passes on Linux), lib/project-command-env (Windows PATH separator ; vs :), components/AppShell.file-viewer-state (brittle source-comment-block assertions), hooks/useAgentSession (4 brittle internal-variable regex assertions). These pass on Linux CI or are pre-existing test debt, out of scope here.

Note

This PR is scoped to the test harness only. The pagination feature work (the session-history tail/before changes that Codex reviewed on the earlier branch state) lives in PR #587; the Playwright E2E example for CI lives in the CI PR. No product code in this PR.

Relates to #586.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b028e5fec9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/api/sessions/[id]/route.ts Outdated
Comment on lines +40 to +41
const tail = Number.isFinite(rawTail) && rawTail > 0 ? Math.min(rawTail, 1000) : 50;
const context = buildSessionContext(entries as never, leafId, { deferThinking, deferToolResultImages, tail });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve access to history beyond the initial tail

For any session with more than 50 displayed entries, the normal session load now returns only this default tail, but ChatWindow only mounts the pagination sentinel when the locally loaded render window has hasMore (rendered.length > visibleCount, also 50 initially). That means a long session opens with exactly 50 messages and no sentinel, so the client never calls /context?before=... and the older history is unreachable.

Useful? React with 👍 / 👎.

Comment thread lib/session-reader.ts Outdated
let leaf = leafId ? byId.get(leafId) : entries[entries.length - 1];
// Pagination: `before` is the oldest entry already loaded, so the next page
// must start at its parent to avoid duplicating `before` when prepended.
if (excludeLeaf && leaf?.parentId) leaf = byId.get(leaf.parentId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Return an empty page before the root entry

When the client asks for the page before the first/root entry, excludeLeaf is true but this only rewinds when parentId exists, leaving leaf on the boundary entry. In that case the helper returns the same root entry again, so pagination at the start of a branch prepends a duplicate and can keep refetching it instead of getting an empty page that signals there is no older history.

Useful? React with 👍 / 👎.

Comment thread package.json Outdated
"katex": "^0.16.47",
"mammoth": "^1.12.0",
"mermaid": "^11.16.1",
"playwright": "^1.48.0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Commit the lockfile entry for Playwright

This adds a new dev dependency, but the reviewed commit does not update package-lock.json and the lock still has no root or node_modules/playwright entry. I checked the reviewed package files with npm ci --dry-run, and npm had to resolve playwright from the registry; in locked or registry-restricted installs this makes the new e2e scripts unavailable or the install fail, so the lockfile should be regenerated with this dependency.

Useful? React with 👍 / 👎.

- load react, react-dom/server, and the i18n provider through the same jiti instance the components use, and import useI18n via the @/ alias (matching component imports) so I18nContext resolves to a single module instance.

- previously the test entry imported React natively while jiti loaded the .tsx tree, producing two React instances and two I18nContext modules; useContext then returned null and every component test threw 'useI18n must be used inside I18nProvider'.

- suite now 591 passing / 9 failing (was 565/35). Remaining 9 are platform-conditional (symlink, Windows PATH separator) or pre-existing brittle source-structure assertions, not harness defects.

- Relates to agegr#586.
@Nuctori
Nuctori force-pushed the fix/test-harness-react-instance branch from b028e5f to 1e5594b Compare August 23, 2026 20:33
@Nuctori

Nuctori commented Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

Branch rebuilt from main so this PR is scoped to the harness fix only (the earlier branch state accidentally carried the pagination feature from #587 as well). Codex's P1/P2 notes about the detail route (�pp/api/sessions/[id]/route.ts), lib/session-reader.ts, ChatWindow.tsx, and the playwright lockfile belong to PR #587, not this harness PR — they are addressed there (see #587). This harness PR touches no product code and no package.json.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants