mirror of
https://github.com/turbot/steampipe.git
synced 2025-12-19 18:12:43 -05:00
* Add test for #4810: getQueryInfo() fails to detect 'from ' correctly This test demonstrates that getQueryInfo("from ") incorrectly returns EditingTable = false when it should return true. This prevents autocomplete from suggesting tables after users type "from ". The test currently fails as expected, proving the bug exists. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix #4810: Correct getQueryInfo() 'from ' detection for autocomplete This commit fixes a bug where getQueryInfo("from ") incorrectly returned EditingTable = false, preventing autocomplete from suggesting tables after users type "from ". The fix involves two changes: 1. Modified getPreviousWord() to correctly return "from" when the input is "from " (single word followed by space). Previously, it returned an empty string because it couldn't find a space before "from". 2. Modified isEditingTable() to check that the text ends with a space. This ensures we only enable table suggestions when the user has typed "from " (ready for a table name), not when they're in the middle of typing "from" or after they've already started typing a table name like "from my_table". The combination of these changes ensures: - "from " → EditingTable = true (autocomplete shows tables) - "from my_table" → EditingTable = false (autocomplete doesn't interfere) - "from" → EditingTable = false (no space yet, not ready for table name) All existing tests pass, and the new test from the previous commit now passes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -580,3 +580,53 @@ func TestInitialisationComplete_RaceCondition(t *testing.T) {
|
|||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestGetQueryInfo_FromDetection tests that getQueryInfo correctly detects
|
||||||
|
// when the user is editing a table name after typing "from ".
|
||||||
|
//
|
||||||
|
// This is important for autocomplete - when a user types "from " (with a space),
|
||||||
|
// the system should recognize they are about to enter a table name and enable
|
||||||
|
// table suggestions.
|
||||||
|
//
|
||||||
|
// Bug: #4810
|
||||||
|
func TestGetQueryInfo_FromDetection(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input string
|
||||||
|
expectedTable string
|
||||||
|
expectedEditTable bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "just_from",
|
||||||
|
input: "from ",
|
||||||
|
expectedTable: "",
|
||||||
|
expectedEditTable: true, // Should be true - user is about to enter table name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "from_with_table",
|
||||||
|
input: "from my_table",
|
||||||
|
expectedTable: "my_table",
|
||||||
|
expectedEditTable: false, // Not editing, already entered
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "from_keyword_only",
|
||||||
|
input: "from",
|
||||||
|
expectedTable: "",
|
||||||
|
expectedEditTable: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
result := getQueryInfo(tt.input)
|
||||||
|
|
||||||
|
if result.Table != tt.expectedTable {
|
||||||
|
t.Errorf("getQueryInfo(%q).Table = %q, expected %q", tt.input, result.Table, tt.expectedTable)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.EditingTable != tt.expectedEditTable {
|
||||||
|
t.Errorf("getQueryInfo(%q).EditingTable = %v, expected %v", tt.input, result.EditingTable, tt.expectedEditTable)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,12 +17,16 @@ func getQueryInfo(text string) *queryCompletionInfo {
|
|||||||
|
|
||||||
return &queryCompletionInfo{
|
return &queryCompletionInfo{
|
||||||
Table: table,
|
Table: table,
|
||||||
EditingTable: isEditingTable(prevWord),
|
EditingTable: isEditingTable(text, prevWord),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isEditingTable(prevWord string) bool {
|
func isEditingTable(text string, prevWord string) bool {
|
||||||
var editingTable = prevWord == "from"
|
// Only consider it editing table if:
|
||||||
|
// 1. The previous word is "from"
|
||||||
|
// 2. The text ends with a space (meaning cursor is after "from ", not in the middle of typing a table name)
|
||||||
|
endsWithSpace := len(text) > 0 && text[len(text)-1] == ' '
|
||||||
|
var editingTable = prevWord == "from" && endsWithSpace
|
||||||
return editingTable
|
return editingTable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +56,8 @@ func getPreviousWord(text string) string {
|
|||||||
}
|
}
|
||||||
prevSpace := strings.LastIndex(text[:lastNotSpace], " ")
|
prevSpace := strings.LastIndex(text[:lastNotSpace], " ")
|
||||||
if prevSpace == -1 {
|
if prevSpace == -1 {
|
||||||
return ""
|
// No space before the word, so return from the beginning to lastNotSpace
|
||||||
|
return text[0 : lastNotSpace+1]
|
||||||
}
|
}
|
||||||
return text[prevSpace+1 : lastNotSpace+1]
|
return text[prevSpace+1 : lastNotSpace+1]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,9 +200,9 @@ func TestGetPreviousWord(t *testing.T) {
|
|||||||
expected: "from",
|
expected: "from",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no previous word",
|
name: "single word with trailing space",
|
||||||
input: "select ",
|
input: "select ",
|
||||||
expected: "",
|
expected: "select",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single word",
|
name: "single word",
|
||||||
@@ -324,31 +324,43 @@ func TestGetTable(t *testing.T) {
|
|||||||
func TestIsEditingTable(t *testing.T) {
|
func TestIsEditingTable(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
text string
|
||||||
prevWord string
|
prevWord string
|
||||||
expected bool
|
expected bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "from keyword",
|
name: "from keyword with trailing space",
|
||||||
|
text: "from ",
|
||||||
prevWord: "from",
|
prevWord: "from",
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "from keyword without trailing space",
|
||||||
|
text: "from",
|
||||||
|
prevWord: "from",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "not from keyword",
|
name: "not from keyword",
|
||||||
|
text: "select ",
|
||||||
prevWord: "select",
|
prevWord: "select",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty string",
|
name: "empty string",
|
||||||
|
text: "",
|
||||||
prevWord: "",
|
prevWord: "",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "FROM uppercase",
|
name: "FROM uppercase",
|
||||||
|
text: "FROM ",
|
||||||
prevWord: "FROM",
|
prevWord: "FROM",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "whitespace",
|
name: "whitespace",
|
||||||
|
text: " from ",
|
||||||
prevWord: " from ",
|
prevWord: " from ",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
@@ -356,9 +368,9 @@ func TestIsEditingTable(t *testing.T) {
|
|||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
result := isEditingTable(tt.prevWord)
|
result := isEditingTable(tt.text, tt.prevWord)
|
||||||
if result != tt.expected {
|
if result != tt.expected {
|
||||||
t.Errorf("isEditingTable(%q) = %v, want %v", tt.prevWord, result, tt.expected)
|
t.Errorf("isEditingTable(%q, %q) = %v, want %v", tt.text, tt.prevWord, result, tt.expected)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user