printer: adds unit tests to reach 100% test coverage#745
Conversation
📝 WalkthroughWalkthroughThis PR fixes two bugs in the GraphQL AST printer and introduces a comprehensive internal test suite. The ChangesPrinter Bug Fixes and Test Suite
🎯 3 (Moderate) | ⏱️ ~25 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 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: 2
🤖 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 `@language/printer/printer_internal_test.go`:
- Around line 277-281: The test currently only checks action ==
visitor.ActionUpdate and then discards val, which lets regressions in
OperationDefinition formatting pass; update the assertions in the
OperationDefinition test cases (the blocks that check action and set val) to
assert on val's concrete value/shape instead of `_ = val` — e.g., verify the
returned string contains the expected operation name and formatting (for the
cases covering lines around the `if action != visitor.ActionUpdate {` check),
replacing the `_ = val` placeholders with assertions that validate val is a
non-empty string and matches the expected operation-name formatting for each
OperationDefinition test case.
In `@language/printer/printer.go`:
- Around line 42-47: The loop in getMapSliceValue prematurely exits when the
type-switch on v (switch v := v.(type)) hits a non-slice branch because of the
stray "break", preventing traversal of dotted keys like "a.b"; remove that break
(or replace it with no-op/continue) so the for-loop can continue and allow
map[string]interface{} traversal to proceed, keeping only the case []interface{}
returning the slice and otherwise falling through to the existing map-access
logic in getMapSliceValue.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0e6d4af3-b61f-4c23-9b30-ef060a6aec0e
📒 Files selected for processing (2)
language/printer/printer.golanguage/printer/printer_internal_test.go
| if action != visitor.ActionUpdate { | ||
| t.Fatalf("expected ActionUpdate, got %v", action) | ||
| } | ||
| _ = val | ||
|
|
There was a problem hiding this comment.
Assert reducer output for OperationDefinition cases.
Lines 280, 306, and 325 discard val, so these tests can still pass if operation-name formatting regresses. Since this PR fixes that behavior, these should assert returned string shape/content.
Suggested assertion pattern
import (
"fmt"
+ "strings"
"testing"
@@
- _ = val
+ got, ok := val.(string)
+ if !ok {
+ t.Fatalf("expected string output, got %T", val)
+ }
+ if strings.HasPrefix(got, "query ") || strings.Contains(got, "<nil>") {
+ t.Fatalf("unexpected anonymous query format: %q", got)
+ }
@@
- _ = val2
+ got2, ok := val2.(string)
+ if !ok {
+ t.Fatalf("expected string output, got %T", val2)
+ }
+ if !strings.Contains(got2, "mutation myMutation") {
+ t.Fatalf("unexpected mutation format: %q", got2)
+ }
@@
- _ = val3
+ got3, ok := val3.(string)
+ if !ok {
+ t.Fatalf("expected string output, got %T", val3)
+ }
+ if !strings.HasPrefix(got3, "subscription ") {
+ t.Fatalf("unexpected subscription format: %q", got3)
+ }Also applies to: 303-307, 322-326
🤖 Prompt for 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.
In `@language/printer/printer_internal_test.go` around lines 277 - 281, The test
currently only checks action == visitor.ActionUpdate and then discards val,
which lets regressions in OperationDefinition formatting pass; update the
assertions in the OperationDefinition test cases (the blocks that check action
and set val) to assert on val's concrete value/shape instead of `_ = val` —
e.g., verify the returned string contains the expected operation name and
formatting (for the cases covering lines around the `if action !=
visitor.ActionUpdate {` check), replacing the `_ = val` placeholders with
assertions that validate val is a non-empty string and matches the expected
operation-name formatting for each OperationDefinition test case.
| switch v := v.(type) { | ||
| case []interface{}: | ||
| return v | ||
| default: | ||
| return []interface{}{} | ||
| } | ||
| break | ||
| } |
There was a problem hiding this comment.
Restore nested map traversal in getMapSliceValue.
Line 46 breaks the loop for any non-slice token, so dotted keys (for example "a.b") cannot traverse nested maps at all. That makes this helper inconsistent with the other dotted-path helpers and can return incorrect empty results for valid nested map inputs.
Suggested fix
func getMapSliceValue(m map[string]interface{}, key string) []interface{} {
tokens := strings.Split(key, ".")
valMap := m
for _, token := range tokens {
v, ok := valMap[token]
if !ok {
return []interface{}{}
}
switch v := v.(type) {
case []interface{}:
return v
+ case map[string]interface{}:
+ valMap = v
+ continue
+ default:
+ return []interface{}{}
}
- break
}
return []interface{}{}
}📝 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.
| switch v := v.(type) { | |
| case []interface{}: | |
| return v | |
| default: | |
| return []interface{}{} | |
| } | |
| break | |
| } | |
| func getMapSliceValue(m map[string]interface{}, key string) []interface{} { | |
| tokens := strings.Split(key, ".") | |
| valMap := m | |
| for _, token := range tokens { | |
| v, ok := valMap[token] | |
| if !ok { | |
| return []interface{}{} | |
| } | |
| switch v := v.(type) { | |
| case []interface{}: | |
| return v | |
| case map[string]interface{}: | |
| valMap = v | |
| continue | |
| default: | |
| return []interface{}{} | |
| } | |
| } | |
| return []interface{}{} | |
| } |
🤖 Prompt for 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.
In `@language/printer/printer.go` around lines 42 - 47, The loop in
getMapSliceValue prematurely exits when the type-switch on v (switch v :=
v.(type)) hits a non-slice branch because of the stray "break", preventing
traversal of dotted keys like "a.b"; remove that break (or replace it with
no-op/continue) so the for-loop can continue and allow map[string]interface{}
traversal to proceed, keeping only the case []interface{} returning the slice
and otherwise falling through to the existing map-access logic in
getMapSliceValue.
Details
printer: adds unit tests to reach 100% test coverageTest Plan
Summary by CodeRabbit
Bug Fixes
Tests