test: finops + tool-lookup — RBAC formatting and Zod schema introspection#397
test: finops + tool-lookup — RBAC formatting and Zod schema introspection#397anandgupta42 wants to merge 1 commit intomainfrom
Conversation
…tion coverage Adds 14 tests for two untested modules: tool_lookup Zod schema introspection (used by the agent to discover tool contracts) and finops role-access formatting functions (renders RBAC grants, hierarchy, and user-role assignments for audits). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> https://claude.ai/code/session_01PnbJpBRPw8DrqSBDxhrCjg
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review.
Tip: disable this comment in your organization's Code Review settings.
📝 WalkthroughWalkthroughTwo new Bun test files added to validate finops role-access formatting tools and ToolLookupTool's Zod schema introspection. Tests stub dispatcher calls with deterministic RBAC payloads and assert correct markdown output formatting, fallback alias handling, empty state behavior, and error reporting. Total 397 lines added across both files. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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
🧹 Nitpick comments (2)
packages/opencode/test/altimate/finops-role-access.test.ts (1)
18-23: Restore telemetry env value instead of unconditional delete.Unconditionally deleting the env key can alter parent process config for later tests. Restore the prior value on teardown.
♻️ Proposed fix
+const previousTelemetryDisabled = process.env.ALTIMATE_TELEMETRY_DISABLED + beforeEach(() => { process.env.ALTIMATE_TELEMETRY_DISABLED = "true" }) afterAll(() => { - delete process.env.ALTIMATE_TELEMETRY_DISABLED + if (previousTelemetryDisabled === undefined) { + delete process.env.ALTIMATE_TELEMETRY_DISABLED + } else { + process.env.ALTIMATE_TELEMETRY_DISABLED = previousTelemetryDisabled + } })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/test/altimate/finops-role-access.test.ts` around lines 18 - 23, The test currently sets process.env.ALTIMATE_TELEMETRY_DISABLED = "true" in beforeEach and unconditionally deletes it in afterAll; change this to capture the prior value before setting (e.g., store in a variable in the test scope), set the env in beforeEach, and in afterAll restore the previous value (if undefined, delete the key; otherwise set it back) so process.env.ALTIMATE_TELEMETRY_DISABLED is returned to its original state; update the beforeEach/afterAll blocks in finops-role-access.test.ts accordingly.packages/opencode/test/altimate/tool-lookup.test.ts (1)
16-21: Preserve pre-existing telemetry env state during cleanup.
afterAllalways deletesALTIMATE_TELEMETRY_DISABLED, which can clobber a pre-set value from the parent test process. Restore the previous value instead of always deleting.♻️ Proposed fix
+const previousTelemetryDisabled = process.env.ALTIMATE_TELEMETRY_DISABLED + beforeEach(() => { process.env.ALTIMATE_TELEMETRY_DISABLED = "true" }) afterAll(() => { - delete process.env.ALTIMATE_TELEMETRY_DISABLED + if (previousTelemetryDisabled === undefined) { + delete process.env.ALTIMATE_TELEMETRY_DISABLED + } else { + process.env.ALTIMATE_TELEMETRY_DISABLED = previousTelemetryDisabled + } })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/test/altimate/tool-lookup.test.ts` around lines 16 - 21, The test currently sets process.env.ALTIMATE_TELEMETRY_DISABLED in beforeEach and unconditionally deletes it in afterAll, which can clobber a parent process value; modify the setup to capture the original value (e.g., const prevTelemetry = process.env.ALTIMATE_TELEMETRY_DISABLED) before changing it in beforeEach and then in afterAll restore process.env.ALTIMATE_TELEMETRY_DISABLED = prevTelemetry (or delete it only if prevTelemetry was undefined) so that the original environment state is preserved; update the beforeEach/afterAll blocks (referencing beforeEach, afterAll, and ALTIMATE_TELEMETRY_DISABLED) accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/opencode/test/altimate/finops-role-access.test.ts`:
- Around line 38-43: The mockDispatcher implementation incorrectly treats falsy
mocked values as missing; replace the truthiness check in mockDispatcher
(currently `if (responses[method])`) with a property-existence check such as
using Object.prototype.hasOwnProperty.call(responses, method) or the `in`
operator so Dispatcher.call mock returns falsy-but-valid responses instead of
throwing "No mock for ...".
---
Nitpick comments:
In `@packages/opencode/test/altimate/finops-role-access.test.ts`:
- Around line 18-23: The test currently sets
process.env.ALTIMATE_TELEMETRY_DISABLED = "true" in beforeEach and
unconditionally deletes it in afterAll; change this to capture the prior value
before setting (e.g., store in a variable in the test scope), set the env in
beforeEach, and in afterAll restore the previous value (if undefined, delete the
key; otherwise set it back) so process.env.ALTIMATE_TELEMETRY_DISABLED is
returned to its original state; update the beforeEach/afterAll blocks in
finops-role-access.test.ts accordingly.
In `@packages/opencode/test/altimate/tool-lookup.test.ts`:
- Around line 16-21: The test currently sets
process.env.ALTIMATE_TELEMETRY_DISABLED in beforeEach and unconditionally
deletes it in afterAll, which can clobber a parent process value; modify the
setup to capture the original value (e.g., const prevTelemetry =
process.env.ALTIMATE_TELEMETRY_DISABLED) before changing it in beforeEach and
then in afterAll restore process.env.ALTIMATE_TELEMETRY_DISABLED = prevTelemetry
(or delete it only if prevTelemetry was undefined) so that the original
environment state is preserved; update the beforeEach/afterAll blocks
(referencing beforeEach, afterAll, and ALTIMATE_TELEMETRY_DISABLED) accordingly.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 2c75c5fc-dfa1-4a95-a2fe-8a8c556d9a9c
📒 Files selected for processing (2)
packages/opencode/test/altimate/finops-role-access.test.tspackages/opencode/test/altimate/tool-lookup.test.ts
| function mockDispatcher(responses: Record<string, any>) { | ||
| dispatcherSpy?.mockRestore() | ||
| dispatcherSpy = spyOn(Dispatcher, "call").mockImplementation(async (method: string) => { | ||
| if (responses[method]) return responses[method] | ||
| throw new Error(`No mock for ${method}`) | ||
| }) |
There was a problem hiding this comment.
Use key existence check in mockDispatcher, not truthiness.
if (responses[method]) fails for valid mocked values that are falsy. Check property existence to avoid false “No mock” failures.
🐛 Proposed fix
function mockDispatcher(responses: Record<string, any>) {
dispatcherSpy?.mockRestore()
dispatcherSpy = spyOn(Dispatcher, "call").mockImplementation(async (method: string) => {
- if (responses[method]) return responses[method]
+ if (Object.prototype.hasOwnProperty.call(responses, method)) return responses[method]
throw new Error(`No mock for ${method}`)
})
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function mockDispatcher(responses: Record<string, any>) { | |
| dispatcherSpy?.mockRestore() | |
| dispatcherSpy = spyOn(Dispatcher, "call").mockImplementation(async (method: string) => { | |
| if (responses[method]) return responses[method] | |
| throw new Error(`No mock for ${method}`) | |
| }) | |
| function mockDispatcher(responses: Record<string, any>) { | |
| dispatcherSpy?.mockRestore() | |
| dispatcherSpy = spyOn(Dispatcher, "call").mockImplementation(async (method: string) => { | |
| if (Object.prototype.hasOwnProperty.call(responses, method)) return responses[method] | |
| throw new Error(`No mock for ${method}`) | |
| }) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/opencode/test/altimate/finops-role-access.test.ts` around lines 38 -
43, The mockDispatcher implementation incorrectly treats falsy mocked values as
missing; replace the truthiness check in mockDispatcher (currently `if
(responses[method])`) with a property-existence check such as using
Object.prototype.hasOwnProperty.call(responses, method) or the `in` operator so
Dispatcher.call mock returns falsy-but-valid responses instead of throwing "No
mock for ...".
Merges 9 test PRs (#390, #394, #395, #396, #397, #398, #399, #401, #387) into a single PR, discarding 4 duplicates (#391, #392, #393, #400). **New test coverage:** - `id.test.ts` — 14 tests: Identifier generation, monotonic ordering, timestamp extraction, Zod schema - `shell.test.ts` — 9 tests: shell blacklist enforcement for fish/nu, cache reset, fallback - `path-traversal.test.ts` — 7 tests (new): `Protected.isSensitiveWrite` for .pem/.key, .gnupg, .env variants - `ignore.test.ts` — 7 tests (new): `FileIgnore.match` directory patterns, globs, whitelist overrides - `paths-parsetext.test.ts` — 16 tests: `ConfigPaths.parseText` env/file substitution, JSONC parsing - `finops-formatting.test.ts` — 14 tests: `formatBytes`/`truncateQuery` edge cases - `finops-role-access.test.ts` — 10 tests: RBAC `formatGrants`/`formatHierarchy`/`formatUserRoles` - `tool-lookup.test.ts` — 4 tests: Zod schema introspection for tool parameters - `summary-git-path.test.ts` — 10 tests: `unquoteGitPath` decoding for non-ASCII filenames - `tracing.test.ts` — 2 tests (added): Recap loop detection boundaries - `patch.test.ts` — 9 tests (added): `maybeParseApplyPatchVerified` entry point coverage - `instruction.test.ts` — 13 tests (new): `InstructionPrompt.loaded()` dedup guards - `message-v2.test.ts` — 23 tests (new): `MessageV2.filterCompacted()` boundary detection **Bug fixes (discovered during testing):** - `finops-formatting.ts`: fix `formatBytes` crash on negative/NaN/fractional inputs - `finops-formatting.ts`: fix `truncateQuery` returning empty for whitespace-only, exceeding `maxLen` when < 4 - `training-import.test.ts`: fix pre-existing typecheck errors (missing `context`/`rule` mock keys) - `instruction.test.ts`, `message-v2.test.ts`: fix `MessageV2.Part` cast and branded ID type errors Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Consolidated into #403 |
* test: consolidated test coverage across 9 modules (133 new tests) Merges 9 test PRs (#390, #394, #395, #396, #397, #398, #399, #401, #387) into a single PR, discarding 4 duplicates (#391, #392, #393, #400). **New test coverage:** - `id.test.ts` — 14 tests: Identifier generation, monotonic ordering, timestamp extraction, Zod schema - `shell.test.ts` — 9 tests: shell blacklist enforcement for fish/nu, cache reset, fallback - `path-traversal.test.ts` — 7 tests (new): `Protected.isSensitiveWrite` for .pem/.key, .gnupg, .env variants - `ignore.test.ts` — 7 tests (new): `FileIgnore.match` directory patterns, globs, whitelist overrides - `paths-parsetext.test.ts` — 16 tests: `ConfigPaths.parseText` env/file substitution, JSONC parsing - `finops-formatting.test.ts` — 14 tests: `formatBytes`/`truncateQuery` edge cases - `finops-role-access.test.ts` — 10 tests: RBAC `formatGrants`/`formatHierarchy`/`formatUserRoles` - `tool-lookup.test.ts` — 4 tests: Zod schema introspection for tool parameters - `summary-git-path.test.ts` — 10 tests: `unquoteGitPath` decoding for non-ASCII filenames - `tracing.test.ts` — 2 tests (added): Recap loop detection boundaries - `patch.test.ts` — 9 tests (added): `maybeParseApplyPatchVerified` entry point coverage - `instruction.test.ts` — 13 tests (new): `InstructionPrompt.loaded()` dedup guards - `message-v2.test.ts` — 23 tests (new): `MessageV2.filterCompacted()` boundary detection **Bug fixes (discovered during testing):** - `finops-formatting.ts`: fix `formatBytes` crash on negative/NaN/fractional inputs - `finops-formatting.ts`: fix `truncateQuery` returning empty for whitespace-only, exceeding `maxLen` when < 4 - `training-import.test.ts`: fix pre-existing typecheck errors (missing `context`/`rule` mock keys) - `instruction.test.ts`, `message-v2.test.ts`: fix `MessageV2.Part` cast and branded ID type errors Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address code review findings — test artifact leakage and cleanup - summary-git-path.test.ts: use tmpdir() instead of projectRoot to prevent Storage.write() from polluting the developer's .opencode/storage/ directory - finops-role-access.test.ts: consolidate duplicate afterAll hooks to ensure ALTIMATE_TELEMETRY_DISABLED env var is cleaned up after tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
What does this PR do?
Adds 14 new tests covering two completely untested modules that have real user-facing risk.
1.
ToolLookupTool—src/altimate/tools/tool-lookup.ts(4 new tests)The agent uses
tool_lookupto discover other tools' parameter contracts before calling them. The module containsdescribeZodSchema,inferZodType,unwrap, andgetShape— pure functions that introspect Zod's internal_defstructure (not a stable public API). Zero tests existed. If a Zod upgrade changes internals or a wrapper type isn't handled byunwrap, the agent silently gets wrong parameter info and makes incorrect tool calls.New coverage includes:
z.string().optional().default(...))"No parameters."path)2.
FinopsRoleAccessformatting —src/altimate/tools/finops-role-access.ts(10 new tests)The
formatGrants,formatHierarchy, andformatUserRolesfunctions render RBAC data as tables for data engineers auditing Snowflake permissions. Zero tests existed. Incorrect output could cause engineers to miss security issues.New coverage includes:
formatGrants: privilege summary rendering, grant table with standard Snowflake fields, fallback field aliases (grantee_namevsrole,object_typevsgranted_on,object_namevsname), empty grants, Dispatcher failure error pathformatHierarchy: recursive two-level tree rendering withchildrenkey,granted_rolesfallback alias, empty hierarchyformatUserRoles: standard field rendering, fallback aliases (user_name,role_name,grantor), empty assignmentsTests use
Dispatcher.callspying (established pattern fromimpact-analysis.test.ts) to supply known RBAC data without requiring a real warehouse connection.Type of change
Issue for this PR
N/A — proactive test coverage
How did you verify your code works?
Checklist
https://claude.ai/code/session_01PnbJpBRPw8DrqSBDxhrCjg
Summary by CodeRabbit