test: property-check table formatter alignment under unicode content - #595
Conversation
Four fast-check properties over buildTable/buildTableRow with cell content mixing ASCII, CJK, and emoji so widths are exercised in display columns rather than UTF-16 units (ui-02): - every line of any table (header, separator, all rows) has exactly the layout's display width, for any column set, alignment mix, missing cells, or extra cells beyond the column count - content that fits is preserved verbatim with padding on the declared side - overflowing content truncates to a prefix of the original plus an ellipsis, never exceeding the column width even when a wide glyph cannot fill the final column - zero-width columns render empty and never leak an ellipsis that would desync the row from the header layout Companion to the property suites in #574/#575/#592-#594. https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
|
Warning Review limit reached
More reviews will be available in 29 minutes and 53 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughproperty test suite validates ChangesTable formatter property tests
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes flagged observations
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@test/property/table-formatter.property.test.ts`:
- Around line 77-98: Add a symmetric property test for right-aligned truncation:
copy the existing test block that uses buildTableRow, arbCellText and
displayWidth but set columns: [{ header: "h", width, align: "right" }], strip
leading padding with visible = row.replace(/^ +/, "") (instead of trimming
trailing spaces), and assert the same properties: visible endsWith("…"), the
original value startsWith(visible.slice(0, -1)), and displayWidth(visible) <=
width to verify truncation + ellipsis is correct for right alignment.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: b0ba59fb-bdf9-4f95-b979-75cf5197b9fd
📒 Files selected for processing (1)
test/property/table-formatter.property.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,js,mts,cjs}
📄 CodeRabbit inference engine (AGENTS.md)
Use ESM only with
"type": "module"in package.json; Node >= 18.17 required
Files:
test/property/table-formatter.property.test.ts
**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Do not use
as any,@ts-ignore, or@ts-expect-errorTypeScript assertions
Files:
test/property/table-formatter.property.test.ts
**/*.{ts,js}
📄 CodeRabbit inference engine (AGENTS.md)
OAuth callback server uses port 1455; do not hardcode OAuth ports—use existing constants/helpers
Files:
test/property/table-formatter.property.test.ts
**/*.{js,ts}
📄 CodeRabbit inference engine (README.md)
**/*.{js,ts}: Use JSON format for machine-readable output in diagnostic and reporting commands (status, check, report, monitor, why-selected)
Implement interactive terminal dashboard with hotkeys (Up/Down for navigation, Enter for selection, 1-9 for quick switch, / for search, ? for help, Q for back)
Support device authentication flow via --device-auth flag and manual OAuth callback paste fallback via --manual flag for headless environments
Run npm version check during normal forwarded Codex startup and print upgrade notices only on interactive TTY or when CODEX_MULTI_AUTH_DEBUG=1 is set
Files:
test/property/table-formatter.property.test.ts
test/**/*.test.ts
📄 CodeRabbit inference engine (test/AGENTS.md)
test/**/*.test.ts: Write Vitest test suites with globals enabled (describe, it, expect)
Maintain 80%+ coverage threshold across statements, branches, functions, and lines
Use removeWithRetry() for Windows filesystem cleanup instead of bare fs.rm to handle EBUSY, EPERM, and ENOTEMPTY errors
Do not rely on dist/ in tests; use source files instead
Do not skip tests without justification
Relax lint rules for test files as configured in eslint.config.js
Files:
test/property/table-formatter.property.test.ts
test/**/property/**/*.test.ts
📄 CodeRabbit inference engine (test/AGENTS.md)
Use fast-check for property-based testing in test files
Files:
test/property/table-formatter.property.test.ts
test/**
⚙️ CodeRabbit configuration file
tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.
Files:
test/property/table-formatter.property.test.ts
**
⚙️ CodeRabbit configuration file
**: # PROJECT KNOWLEDGE BASEGenerated: 2026-04-25
Commit: a87e005
Validated: 2026-06-10 against commit 98d9819 (repo audit; claims re-checked against the tree, content not regenerated)
Branch: main
Package version: 2.3.0-beta.3OVERVIEW
codex-multi-authis a Codex CLI-first OAuth account manager and optional forwarding wrapper for the official Codex CLI. The installedcodex-multi-authentrypoint handles account-management commands locally,codex-multi-auth-codexforwards official Codex commands through this package's wrapper when explicitly used, and runtime rotation can route live Responses traffic through a localhost account-rotation proxy by default. The plugin-host entrypoint remains exported for compatibility, but the primary product surface is the account manager, optional wrapper, storage, runtime proxy, and repair tooling.STRUCTURE
./ ├── scripts/ │ ├── codex.js # codex-multi-auth-codex wrapper, official CLI forwarder, shadow CODEX_HOME/runtime proxy setup │ ├── codex-multi-auth.js # standalone package CLI entrypoint │ ├── codex-routing.js # auth command and compatibility alias routing │ ├── codex-bin-resolver.js # official Codex binary discovery │ ├── codex-app-router.js # persistent localhost router for packaged Codex app bind │ └── codex-app-launcher.js # reversible user-level app launcher routing helper ├── index.ts # optional plugin-host runtime entry ├── lib/ # core runtime logic (see lib/AGENTS.md) │ ├── auth/ # OAuth flow, PKCE, callback server │ ├── runtime/ # Codex CLI/app integration helpers, app bind, live sync, runtime observability │ ├── request/ # request transform, SSE, failover, backoff │ ├── storage/ # path resolution, migrations, backups, restore, import/export │ ├── codex-cli/ # Codex CLI state sync and writer helpers │ ├── codex-manager/ # command modules and...
Files:
test/property/table-formatter.property.test.ts
🧠 Learnings (2)
📚 Learning: 2026-06-04T06:14:18.093Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/scheduling-strategy-config.test.ts:1-1
Timestamp: 2026-06-04T06:14:18.093Z
Learning: In ndycode/codex-multi-auth, do not flag explicit imports from "vitest" (e.g., describe, it, expect, beforeEach/afterEach, etc.) in test files as issues—even if the Vitest config sets `globals: true`. The repo’s established convention is to keep these imports for consistency with neighboring tests; removing them would make files outliers.
Applied to files:
test/property/table-formatter.property.test.ts
📚 Learning: 2026-06-04T06:14:24.975Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/runtime-rotation-proxy.test.ts:2478-2491
Timestamp: 2026-06-04T06:14:24.975Z
Learning: In ndycode/codex-multi-auth test files (e.g. `test/*.test.ts`), when creating V3 storage fixtures for accounts, it’s an intentional convention to use `as never` for deliberately minimal stored-account objects that only include `refreshToken`, `addedAt`, and `lastUsed`. Do not treat `as never` here as a type-safety problem: optional/other fields are expected to be populated by the runtime during execution, and the cast is used solely to keep the fixture minimal and consistent across existing tests.
Applied to files:
test/property/table-formatter.property.test.ts
🔇 Additional comments (5)
test/property/table-formatter.property.test.ts (5)
1-9: LGTM!
11-33: LGTM!
35-57: LGTM!
59-75: LGTM!
100-109: LGTM!
…align Greptile P1: stripping leading spaces on a right-aligned row conflated alignment padding with spaces that belong to the truncated content (latent spurious failure under a different fast-check seed - e.g. ' a<CJK>' at width 3 right-aligned). Prefix fidelity now checks the left-aligned rendering of the same value, where the cell starts at column 0, while the right-aligned row keeps its width and trailing- ellipsis assertions. Verified at FAST_CHECK_NUM_RUNS=1000. Greptile P2: arbColumn and the fit property now generate undefined align too, exercising formatCell's default-left branch. https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
) * test: property-check plugin health classification and report shape Three fast-check properties over getAccountHealth/formatHealthReport: - counts and status derive exactly from the per-account classification for any pool (timestamps straddling now, undefined fallbacks, health 0..100): healthy iff not rate-limited, not cooling, health >= 50, circuit closed; status partitions empty->healthy, none->unhealthy, some->degraded, all->healthy - an open circuit disqualifies an otherwise perfect account: tripping the account:<index> fallback breaker for any subset is reflected in circuitState, subtracted from healthyAccountCount, and drives the status partition - the formatted report names every account with its health percentage and exactly the flags its classification implies, and the summary lines appear iff their counts are nonzero Companion to the property suites in #574/#575/#592-#595. https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB * test: exercise half-open disqualification and email-aliased circuits Greptile flagged two coverage gaps: the half-open state was unreachable without advancing the clock, and accounts sharing an email silently shared a breaker without an explicit contract. Property 2 now probes open -> half-open under fake timers (both states disqualify, and the report renders the precise circuit flag), pool emails are unique by construction, and a dedicated property pins shared-email accounts to one breaker while distinct emails stay isolated - derived through the same getAccountIdentityKey the SUT uses. https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --------- Co-authored-by: Claude <[email protected]>
Summary
lib/table-formatter.ts, the CLI table renderer whose alignment guarantee (ui-02) is "measure in display columns, not UTF-16 code units". Property generation is the right tool here: the interesting inputs are exactly the awkward ones — CJK doubles, emoji, wide glyphs straddling a truncation boundary, rows with missing or extra cells.What Changed
New
test/property/table-formatter.property.test.ts(4 properties overbuildTable/buildTableRow, cell content drawn from a mixed ASCII/CJK/emoji alphabet):left/right), padding computed in display columns.formatCelldocuments).formatCell).No SUT bugs found; the renderer's geometry held for every generated case.
Validation
npm test -- test/property/table-formatter.property.test.ts test/table-formatter.test.ts— 15/15 (new 4 + existing 11 untouched)npm run typecheck(also via pre-commit hook)npx eslint test/property/table-formatter.property.test.ts --max-warnings=0Docs and Governance Checklist
Risk and Rollback
test/property/suites (explicit vitest imports, plainfc.assert,fc.preto partition fit vs overflow).https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
Generated by Claude Code
note: greptile review for oc-chatgpt-multi-auth. cite files like
lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.Greptile Summary
adds a new property-based test suite for
lib/table-formatter.ts, covering the four core invariants of the unicode-aware table renderer: lockstep layout width, fit-preservation with display-column padding, truncation correctness with wide-glyph boundaries, and zero-width column isolation. the previous review cycle's two issues (undefinedaligncoverage gap, and the right-aligned prefix check conflating padding spaces with content spaces) are both addressed in this version.sum(widths) + (n-1)display columns for any generated column set, content mix, and ragged row length.formatCellis exercised by a standalone property to confirm no ellipsis leaks into the layout.Confidence Score: 5/5
additive test-only change with no production code modifications; the two issues from the prior review cycle are both addressed in this version.
the test file introduces no new runtime code paths, both previously reported correctness issues in the property checks are resolved, the global fast-check seed is correctly applied via vitest setupFiles (confirmed in vitest.config.ts), and the four invariants cover the documented ui-02 display-column contract end-to-end.
no files require special attention.
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[arbCellText\nASCII/CJK/emoji\nmixed alphabet] --> P1 A --> P2 A --> P3 A --> P4 subgraph P1["Property 1: Lockstep Layout"] B[arbOptions\nn columns, widths 0-10\nalign left/right/undefined] --> C[buildTable rows] C --> D{every line\ndisplayWidth ==\nsum widths + n-1?} D -->|yes| OK1[pass] D -->|no| FAIL1[fail] end subgraph P2["Property 2: Fit Preservation"] E[width 1-14\nalign left/right/undef] --> F{fc.pre:\ndisplayWidth <= width} F --> G[buildTableRow single col] G --> H{row == value + pad\nor pad + value?} H -->|yes| OK2[pass] H -->|no| FAIL2[fail] end subgraph P3["Property 3: Truncation Contract"] I[width 1-6\nalign left/right] --> J{fc.pre:\ndisplayWidth > width} J --> K[buildTableRow single col] K --> L{displayWidth == width\nand trimEnd ends with ellipsis?} L --> M[left-aligned side channel\nfor prefix fidelity] M --> N{value.startsWith\nvisible prefix?} N -->|yes| OK3[pass] N -->|no| FAIL3[fail] end subgraph P4["Property 4: Zero-Width Columns"] O[width = 0] --> Q[buildTableRow single col] Q --> R{row == empty string?} R -->|yes| OK4[pass] R -->|no| FAIL4[fail] end%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% flowchart TD A[arbCellText\nASCII/CJK/emoji\nmixed alphabet] --> P1 A --> P2 A --> P3 A --> P4 subgraph P1["Property 1: Lockstep Layout"] B[arbOptions\nn columns, widths 0-10\nalign left/right/undefined] --> C[buildTable rows] C --> D{every line\ndisplayWidth ==\nsum widths + n-1?} D -->|yes| OK1[pass] D -->|no| FAIL1[fail] end subgraph P2["Property 2: Fit Preservation"] E[width 1-14\nalign left/right/undef] --> F{fc.pre:\ndisplayWidth <= width} F --> G[buildTableRow single col] G --> H{row == value + pad\nor pad + value?} H -->|yes| OK2[pass] H -->|no| FAIL2[fail] end subgraph P3["Property 3: Truncation Contract"] I[width 1-6\nalign left/right] --> J{fc.pre:\ndisplayWidth > width} J --> K[buildTableRow single col] K --> L{displayWidth == width\nand trimEnd ends with ellipsis?} L --> M[left-aligned side channel\nfor prefix fidelity] M --> N{value.startsWith\nvisible prefix?} N -->|yes| OK3[pass] N -->|no| FAIL3[fail] end subgraph P4["Property 4: Zero-Width Columns"] O[width = 0] --> Q[buildTableRow single col] Q --> R{row == empty string?} R -->|yes| OK4[pass] R -->|no| FAIL4[fail] endReviews (3): Last reviewed commit: "Merge branch 'main' into claude/audit-76..." | Re-trigger Greptile