1 parent
31a7609604
commit
18d581137c
10 files changed
+157
-3
No files matched your search
@@ -4,7 +4,7 @@ import { acceptCompletion, autocompletion, completionStatus, currentCompletions,
|
||||
import { EditorState } from "@codemirror/state";
|
||||
import { EditorView } from "@codemirror/view";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { completionLabelPresentation } from "@/lib/editor/sqlCompletionPresentation";
|
||||
import { compareSqlCompletions, completionLabelPresentation } from "@/lib/editor/sqlCompletionPresentation";
|
||||
|
||||
describe("SQL completion label presentation", () => {
|
||||
it("filters a custom snippet by trigger while preserving its display label", () => {
|
||||
@@ -44,3 +44,90 @@ describe("SQL completion label presentation", () => {
|
||||
view.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("SQL completion order", () => {
|
||||
it("keeps the current alphabetical tie-break by default", () => {
|
||||
const items = [
|
||||
{ label: "id", type: "column" },
|
||||
{ label: "z_last", type: "column" },
|
||||
{ label: "a_first", type: "column" },
|
||||
];
|
||||
|
||||
expect([...items].sort((a, b) => compareSqlCompletions(a, b, true)).map((item) => item.label)).toEqual(["a_first", "id", "z_last"]);
|
||||
});
|
||||
|
||||
it("preserves database order for column ties without changing their boosts", () => {
|
||||
const items = [
|
||||
{ label: "id", type: "column", boost: 100 },
|
||||
{ label: "z_last", type: "column", boost: 10 },
|
||||
{ label: "a_first", type: "column", boost: 10 },
|
||||
];
|
||||
|
||||
expect([...items].sort((a, b) => compareSqlCompletions(a, b, false)).map((item) => item.label)).toEqual(["id", "z_last", "a_first"]);
|
||||
expect(items.map((item) => item.boost)).toEqual([100, 10, 10]);
|
||||
});
|
||||
|
||||
it("keeps label ordering for non-columns and mixed item types", () => {
|
||||
expect(compareSqlCompletions({ label: "SELECT", type: "keyword" }, { label: "FROM", type: "keyword" }, false)).toBeGreaterThan(0);
|
||||
expect(compareSqlCompletions({ label: "z_column", type: "column" }, { label: "a_table", type: "table" }, false)).toBeGreaterThan(0);
|
||||
expect(compareSqlCompletions({ label: "visible", sortText: "a_sort", type: "snippet" }, { label: "before", type: "keyword" }, false)).toBeLessThan(0);
|
||||
});
|
||||
|
||||
it("preserves database order in CodeMirror when column match scores tie", async () => {
|
||||
const view = new EditorView({
|
||||
parent: document.createElement("div"),
|
||||
state: EditorState.create({
|
||||
extensions: [
|
||||
autocompletion({
|
||||
interactionDelay: 0,
|
||||
compareCompletions: (a, b) => compareSqlCompletions(a, b, false),
|
||||
override: [
|
||||
() => ({
|
||||
from: 0,
|
||||
options: [
|
||||
{ label: "id", type: "column", boost: 100 },
|
||||
{ label: "z_last", type: "column", boost: 10 },
|
||||
{ label: "a_first", type: "column", boost: 10 },
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
startCompletion(view);
|
||||
await expect.poll(() => completionStatus(view.state)).toBe("active");
|
||||
expect(currentCompletions(view.state).map((item) => item.label)).toEqual(["id", "z_last", "a_first"]);
|
||||
view.destroy();
|
||||
});
|
||||
|
||||
it("keeps the default CodeMirror alphabetical tie-break and key priority", async () => {
|
||||
const view = new EditorView({
|
||||
parent: document.createElement("div"),
|
||||
state: EditorState.create({
|
||||
extensions: [
|
||||
autocompletion({
|
||||
interactionDelay: 0,
|
||||
compareCompletions: (a, b) => compareSqlCompletions(a, b, true),
|
||||
override: [
|
||||
() => ({
|
||||
from: 0,
|
||||
options: [
|
||||
{ label: "id", type: "column", boost: 100 },
|
||||
{ label: "z_last", type: "column", boost: 10 },
|
||||
{ label: "a_first", type: "column", boost: 10 },
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
startCompletion(view);
|
||||
await expect.poll(() => completionStatus(view.state)).toBe("active");
|
||||
expect(currentCompletions(view.state).map((item) => item.label)).toEqual(["id", "a_first", "z_last"]);
|
||||
view.destroy();
|
||||
});
|
||||
});
|
||||
@@ -4,6 +4,12 @@ export interface CompletionLabelPresentation {
|
||||
sortText?: string;
|
||||
}
|
||||
|
||||
export interface CompletionSortItem {
|
||||
label: string;
|
||||
sortText?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export function completionLabelPresentation(label: string, filterText?: string): CompletionLabelPresentation {
|
||||
const normalizedFilterText = filterText?.trim();
|
||||
if (!normalizedFilterText || label.toLowerCase().startsWith(normalizedFilterText.toLowerCase())) return { label };
|
||||
@@ -13,3 +19,8 @@ export function completionLabelPresentation(label: string, filterText?: string):
|
||||
sortText: label,
|
||||
};
|
||||
}
|
||||
|
||||
export function compareSqlCompletions(a: CompletionSortItem, b: CompletionSortItem, sortColumnsAlphabetically: boolean): number {
|
||||
if (!sortColumnsAlphabetically && a.type === "column" && b.type === "column") return 0;
|
||||
return (a.sortText || a.label).localeCompare(b.sortText || b.label);
|
||||
}
|
||||
@@ -20,6 +20,7 @@ export const EDITOR_SETTINGS_DRAFT_KEYS = [
|
||||
"showInsertValueHints",
|
||||
"autoAliasTables",
|
||||
"insertSpaceAfterCompletion",
|
||||
"sortCompletionColumnsAlphabetically",
|
||||
"wordWrap",
|
||||
"vimModeEnabled",
|
||||
"autoCloseBrackets",
|
||||
|
||||
Reference in new issue
Block a user