diff --git a/apps/desktop/src/components/editor/QueryEditor.vue b/apps/desktop/src/components/editor/QueryEditor.vue
index e3ed3712d..f033cab04 100644
--- a/apps/desktop/src/components/editor/QueryEditor.vue
+++ b/apps/desktop/src/components/editor/QueryEditor.vue
@@ -1705,7 +1705,16 @@ onMounted(async () => {
highlightActiveLineGutter(),
highlightSpecialChars(),
history(),
- foldGutter(),
+ foldGutter({
+ markerDOM(open: boolean) {
+ const span = document.createElement("span");
+ span.className = "cm-foldMarker-svg";
+ span.innerHTML = open
+ ? ''
+ : '';
+ return span;
+ },
+ }),
drawSelection(),
trimmedSelectionLayer(),
selectionMatchOccurrences(),
@@ -2249,4 +2258,26 @@ defineExpose({ openSearch, openReplace, scrollCursorIntoView });
.query-editor--table-navigation-hover :deep(.cm-line) {
cursor: pointer;
}
+
+:deep(.cm-foldMarker-svg) {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ vertical-align: middle;
+ width: 16px;
+ height: 16px;
+ color: var(--muted-foreground);
+ opacity: 0.65;
+ transition: opacity 0.15s;
+}
+
+:deep(.cm-foldMarker-svg:hover) {
+ opacity: 0.95;
+}
+
+:deep(.cm-foldMarker-svg svg) {
+ display: block;
+ width: 16px;
+ height: 16px;
+}
diff --git a/packages/app-tests/queryStore.test.ts b/packages/app-tests/queryStore.test.ts
index f8c62d285..730a89efc 100644
--- a/packages/app-tests/queryStore.test.ts
+++ b/packages/app-tests/queryStore.test.ts
@@ -157,7 +157,7 @@ test("editing query sql preserves the displayed result editability state", () =>
assert.equal(tab.tableMeta?.tableName, "users");
});
-test("selecting a result run restores its displayed result without changing SQL draft", () => {
+test("selecting a result run restores its displayed result without changing SQL draft", async () => {
setActivePinia(createPinia());
const store = useQueryStore();
const tabId = store.createTab("conn-1", "db");
@@ -187,7 +187,7 @@ test("selecting a result run restores its displayed result without changing SQL
];
tab.activeResultRunId = "run-2";
- store.setActiveResultRun(tabId, "run-1");
+ await store.setActiveResultRun(tabId, "run-1");
assert.equal(tab.sql, "select draft");
assert.equal(tab.activeResultRunId, "run-1");
@@ -196,7 +196,7 @@ test("selecting a result run restores its displayed result without changing SQL
assert.equal(tab.resultBaseSql, "select 1");
});
-test("removing the active result run selects an adjacent run", () => {
+test("removing the active result run selects an adjacent run", async () => {
setActivePinia(createPinia());
const store = useQueryStore();
const tabId = store.createTab("conn-1", "db");
@@ -233,7 +233,7 @@ test("removing the active result run selects an adjacent run", () => {
resultBaseSql: "select 3",
},
];
- store.setActiveResultRun(tabId, "run-2");
+ await store.setActiveResultRun(tabId, "run-2");
assert.equal(store.removeResultRun(tabId, "run-2"), true);
@@ -349,7 +349,7 @@ test("result archives import into a new query tab with switchable runs", async (
},
];
tab.activeResultRunId = "run-2";
- store.setActiveResultRun(tabId, "run-2");
+ await store.setActiveResultRun(tabId, "run-2");
const archive = await store.exportResultArchive(tabId);
assert.ok(archive);
@@ -369,7 +369,7 @@ test("result archives import into a new query tab with switchable runs", async (
assert.deepEqual(imported?.result?.columns, ["two"]);
assert.deepEqual(imported?.result?.rows, [[2]]);
- store.setActiveResultRun(importedTabId, "run-1");
+ await store.setActiveResultRun(importedTabId, "run-1");
assert.deepEqual(imported?.result?.columns, ["one"]);
assert.deepEqual(imported?.result?.rows, [[1]]);
});
@@ -410,6 +410,7 @@ test("completed query executions append result runs and select the latest run",
try {
const tabId = store.createTab("conn-1", "db", "Query");
+ store.toggleResultAutoSave(tabId);
await store.executeTabSql(tabId, "select 1");
await store.executeTabSql(tabId, "select 2");
@@ -421,7 +422,7 @@ test("completed query executions append result runs and select the latest run",
assert.equal(tab?.activeResultRunId, tab?.resultRuns?.[1]?.id);
assert.deepEqual(tab?.result?.columns, ["run_2"]);
- store.setActiveResultRun(tabId, tab!.resultRuns![0]!.id);
+ await store.setActiveResultRun(tabId, tab!.resultRuns![0]!.id);
assert.deepEqual(tab?.result?.columns, ["run_1"]);
} finally {
globalThis.fetch = originalFetch;
@@ -454,6 +455,7 @@ test("failed query executions append switchable error result runs", async () =>
try {
const tabId = store.createTab("conn-1", "db", "Query");
+ store.toggleResultAutoSave(tabId);
await store.executeTabSql(tabId, "select broken");
const tab = store.tabs.find((item) => item.id === tabId);
@@ -467,7 +469,7 @@ test("failed query executions append switchable error result runs", async () =>
}
});
-test("statement result switching is scoped to the active result run", () => {
+test("statement result switching is scoped to the active result run", async () => {
setActivePinia(createPinia());
const store = useQueryStore();
const tabId = store.createTab("conn-1", "db");
@@ -501,13 +503,13 @@ test("statement result switching is scoped to the active result run", () => {
},
];
tab.activeResultRunId = "run-1";
- store.setActiveResultRun(tabId, "run-1");
+ await store.setActiveResultRun(tabId, "run-1");
store.setActiveResultIndex(tabId, 1);
assert.deepEqual(tab.result?.columns, ["b"]);
assert.equal(tab.resultRuns[0]?.activeResultIndex, 1);
- store.setActiveResultRun(tabId, "run-2");
+ await store.setActiveResultRun(tabId, "run-2");
assert.deepEqual(tab.result?.columns, ["c"]);
assert.equal(tab.activeResultIndex, 0);
});