feat(query): jump to PostgreSQL error position from result messages
This commit is contained in:
1 parent
571fc07d85
commit
5a0e74eec6
36 files changed
+2079
-23
No files matched your search
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { Bot, Wrench } from "@lucide/vue";
|
||||
import { Bot, LocateFixed, Wrench } from "@lucide/vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import type { BackendError } from "@/lib/backend/errorUtils";
|
||||
@@ -10,20 +10,28 @@ const props = defineProps<{
|
||||
errorMessage: string;
|
||||
backendError?: BackendError;
|
||||
connectionId?: string;
|
||||
/** Driver-reported error position, when the backend provides one. */
|
||||
errorPosition?: { line: number; column: number };
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
changeConnectionTimeout: [];
|
||||
changeQueryTimeout: [];
|
||||
fixWithAi: [errorMessage: string];
|
||||
locateError: [];
|
||||
}>();
|
||||
|
||||
const { t } = useI18n();
|
||||
const showConnectionTimeout = computed(() => !!props.connectionId && isConnectionTimeoutErrorMessage(props.errorMessage, props.backendError));
|
||||
const showQueryTimeout = computed(() => !!props.connectionId && !showConnectionTimeout.value && isQueryTimeoutErrorMessage(props.errorMessage, props.backendError));
|
||||
const showLocateError = computed(() => !!props.errorPosition);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Button v-if="showLocateError" variant="outline" size="sm" class="h-7 gap-1.5 px-2.5 text-xs" @click="emit('locateError')">
|
||||
<LocateFixed class="h-3.5 w-3.5" />
|
||||
{{ t("editor.locateError", { line: errorPosition!.line, column: errorPosition!.column }) }}
|
||||
</Button>
|
||||
<Button v-if="showConnectionTimeout" variant="outline" size="sm" class="h-7 gap-1.5 px-2.5 text-xs" @click="emit('changeConnectionTimeout')">
|
||||
<Wrench class="h-3.5 w-3.5" />
|
||||
{{ t("editor.changeConnectionTimeout") }}
|
||||
|
||||
@@ -7,17 +7,26 @@ import i18n from "@/i18n";
|
||||
|
||||
const mountedApps: App[] = [];
|
||||
|
||||
async function mountActions(errorMessage: string, onChangeConnectionTimeout = vi.fn()) {
|
||||
async function mountActions(errorMessage: string, options: { onChangeConnectionTimeout?: () => void; errorPosition?: { line: number; column: number }; onLocateError?: () => void } = {}) {
|
||||
const onChangeConnectionTimeout = options.onChangeConnectionTimeout ?? vi.fn();
|
||||
const onLocateError = options.onLocateError ?? vi.fn();
|
||||
const host = document.createElement("div");
|
||||
document.body.appendChild(host);
|
||||
const app = createApp({
|
||||
setup: () => () => h(QueryErrorActions, { errorMessage, connectionId: "postgres-1", onChangeConnectionTimeout }),
|
||||
setup: () => () =>
|
||||
h(QueryErrorActions, {
|
||||
errorMessage,
|
||||
connectionId: "postgres-1",
|
||||
errorPosition: options.errorPosition,
|
||||
onChangeConnectionTimeout,
|
||||
onLocateError,
|
||||
}),
|
||||
});
|
||||
mountedApps.push(app);
|
||||
app.use(i18n);
|
||||
app.mount(host);
|
||||
await nextTick();
|
||||
return { host, onChangeConnectionTimeout };
|
||||
return { host, onChangeConnectionTimeout, onLocateError };
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
@@ -35,6 +44,23 @@ describe("QueryErrorActions", () => {
|
||||
expect(onChangeConnectionTimeout).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("offers a locate-error action when the backend reports a position", async () => {
|
||||
const { host, onLocateError } = await mountActions("ERROR: relation does not exist", {
|
||||
errorPosition: { line: 2, column: 6 },
|
||||
});
|
||||
const locateButton = Array.from(host.querySelectorAll("button")).find((button) => button.textContent?.includes("Locate error"));
|
||||
|
||||
expect(locateButton?.textContent).toContain("line 2, col 6");
|
||||
locateButton?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
expect(onLocateError).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("hides the locate-error action without a position", async () => {
|
||||
const { host } = await mountActions("ERROR: relation does not exist");
|
||||
|
||||
expect(host.textContent).not.toContain("Locate error");
|
||||
});
|
||||
|
||||
it("does not offer connection timeout settings for query timeouts", async () => {
|
||||
const { host } = await mountActions("Query timed out after 30 seconds");
|
||||
|
||||
|
||||
Reference in new issue
Block a user