fix(settings): report apply failures without stalling
This commit is contained in:
1 parent
840082d73b
commit
cddc6a2c40
10 files changed
+74
-3
No files matched your search
@@ -984,13 +984,34 @@ async function persistSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
function applySettingsErrorToast(error: unknown) {
|
||||
toast(t("settings.applyFailed", { error: error instanceof Error ? error.message : String(error) }), 5000);
|
||||
}
|
||||
|
||||
// Shared apply entrypoint used by both "Apply" and "Apply & Close". Persists the
|
||||
// current draft and reports failure explicitly instead of silently swallowing it
|
||||
// (persistSettings() has several awaited persistence steps with no try/catch, so a
|
||||
// rejected save used to leave "Apply" silent and made "Apply & Close" unclosable with
|
||||
// no feedback). Returns whether persistence succeeded so the close path only proceeds
|
||||
// once the settings are actually saved.
|
||||
async function applySettingsForResult(): Promise<boolean> {
|
||||
try {
|
||||
await persistSettings();
|
||||
return true;
|
||||
} catch (error) {
|
||||
applySettingsErrorToast(error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function applySettings() {
|
||||
await persistSettings();
|
||||
await applySettingsForResult();
|
||||
}
|
||||
|
||||
async function applySettingsAndClose() {
|
||||
await persistSettings();
|
||||
closeSettings();
|
||||
if (await applySettingsForResult()) {
|
||||
closeSettings();
|
||||
}
|
||||
}
|
||||
|
||||
async function restartDbxForDuckDbIsolation() {
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const dialogSource = readFileSync(new URL("../EditorSettingsDialog.vue", import.meta.url), "utf8");
|
||||
|
||||
// Regression for https://github.com/t8y2/dbx/issues/6485: applying editor
|
||||
// settings (e.g. the editor font) could appear to "do nothing" because
|
||||
// persistSettings() has several awaited persistence steps with no error
|
||||
// handling. On a rejected save, "Apply" was completely silent and "Apply &
|
||||
// Close" never called closeSettings(), leaving the dialog stuck open with no
|
||||
// feedback at all.
|
||||
describe("EditorSettingsDialog apply persistence error handling", () => {
|
||||
it("shares a single apply entrypoint between Apply and Apply & Close", () => {
|
||||
// Both buttons must go through one shared persist/apply routine instead of
|
||||
// each calling persistSettings() directly with divergent semantics.
|
||||
const block = dialogSource.slice(dialogSource.indexOf("function applySettingsErrorToast"), dialogSource.indexOf("async function restartDbxForDuckDbIsolation()"));
|
||||
const entrypointCalls = (block.match(/await applySettingsForResult\(\)/g) || []).length;
|
||||
// one call in applySettings() + one (guarded) call in applySettingsAndClose()
|
||||
expect(entrypointCalls).toBeGreaterThanOrEqual(2);
|
||||
// the shared entrypoint exists and wraps persistSettings
|
||||
expect(block).toContain("async function applySettingsForResult(): Promise<boolean>");
|
||||
expect(block).toContain("await persistSettings();");
|
||||
});
|
||||
|
||||
it("never closes the dialog before persistence succeeds", () => {
|
||||
// "Apply & Close" must only proceed to closeSettings() after a successful
|
||||
// apply. Before the fix, closeSettings() ran unconditionally after
|
||||
// `await persistSettings()`, so a rejected save left the dialog stuck open.
|
||||
const block = dialogSource.slice(dialogSource.indexOf("async function applySettingsAndClose()"), dialogSource.indexOf("async function restartDbxForDuckDbIsolation()"));
|
||||
expect(block).toMatch(/if \(await applySettingsForResult\(\)\) \{\s*\n\s*closeSettings\(\);/);
|
||||
});
|
||||
|
||||
it("surfaces persistence failures instead of silently swallowing them", () => {
|
||||
const resultBlock = dialogSource.slice(dialogSource.indexOf("async function applySettingsForResult()"), dialogSource.indexOf("async function applySettings()"));
|
||||
expect(resultBlock).toContain("try {");
|
||||
expect(resultBlock).toContain("catch (error)");
|
||||
expect(resultBlock).toContain("applySettingsErrorToast(error)");
|
||||
expect(resultBlock).toContain("return false;");
|
||||
// a user-facing message is wired up (and translated in every locale)
|
||||
expect(dialogSource).toContain('toast(t("settings.applyFailed"');
|
||||
});
|
||||
});
|
||||
@@ -5822,6 +5822,7 @@ export default {
|
||||
duckDbWorkerProcessIsolationRestartRequired: "Restart DBX for this change to take effect.",
|
||||
restartDbx: "Restart DBX",
|
||||
restartDbxFailed: "Failed to restart DBX: {error}",
|
||||
applyFailed: "Failed to apply settings: {error}",
|
||||
unsavedChangesCloseTitle: "Unsaved changes",
|
||||
unsavedChangesCloseMessage: "You have unsaved settings changes that will be lost if you close now. Discard these changes?",
|
||||
unsavedChangesCloseCancel: "Keep editing",
|
||||
|
||||
@@ -5563,6 +5563,7 @@ export default withEnglishFallback({
|
||||
duckDbWorkerProcessIsolationRestartRequired: "Reinicia DBX para que este cambio surta efecto.",
|
||||
restartDbx: "Reiniciar DBX",
|
||||
restartDbxFailed: "No se pudo reiniciar DBX: {error}",
|
||||
applyFailed: "No se pudieron aplicar los ajustes: {error}",
|
||||
unsavedChangesCloseTitle: "Cambios sin guardar",
|
||||
unsavedChangesCloseMessage: "Tienes cambios de configuración sin guardar que se perderán si cierras ahora. ¿Descartar estos cambios?",
|
||||
unsavedChangesCloseCancel: "Seguir editando",
|
||||
|
||||
@@ -5563,6 +5563,7 @@ export default withEnglishFallback({
|
||||
duckDbWorkerProcessIsolationRestartRequired: "Riavvia DBX affinché questa modifica abbia effetto.",
|
||||
restartDbx: "Riavvia DBX",
|
||||
restartDbxFailed: "Impossibile riavviare DBX: {error}",
|
||||
applyFailed: "Impossibile applicare le impostazioni: {error}",
|
||||
unsavedChangesCloseTitle: "Modifiche non salvate",
|
||||
unsavedChangesCloseMessage: "Ci sono modifiche alle impostazioni non salvate che andranno perse se chiudi ora. Vuoi scartare queste modifiche?",
|
||||
unsavedChangesCloseCancel: "Continua a modificare",
|
||||
|
||||
@@ -5598,6 +5598,7 @@ export default withEnglishFallback({
|
||||
duckDbWorkerProcessIsolationRestartRequired: "この変更を有効にするには DBX を再起動してください。",
|
||||
restartDbx: "DBX を再起動",
|
||||
restartDbxFailed: "DBX の再起動に失敗しました: {error}",
|
||||
applyFailed: "設定の適用に失敗しました: {error}",
|
||||
unsavedChangesCloseTitle: "未保存の変更",
|
||||
unsavedChangesCloseMessage: "未保存の設定変更があります。今すぐ閉じると失われます。これらの変更を破棄しますか?",
|
||||
unsavedChangesCloseCancel: "編集を続ける",
|
||||
|
||||
@@ -5291,6 +5291,7 @@ export default withEnglishFallback({
|
||||
duckDbWorkerProcessIsolationRestartRequired: "이 변경 사항을 적용하려면 DBX를 다시 시작하세요.",
|
||||
restartDbx: "DBX 다시 시작",
|
||||
restartDbxFailed: "DBX 다시 시작 실패: {error}",
|
||||
applyFailed: "설정 적용 실패: {error}",
|
||||
unsavedChangesCloseTitle: "저장하지 않은 변경 사항",
|
||||
unsavedChangesCloseMessage: "저장하지 않은 설정 변경 사항이 있습니다. 지금 닫으면 사라집니다. 이 변경 사항을 취소하시겠습니까?",
|
||||
unsavedChangesCloseCancel: "계속 편집",
|
||||
|
||||
@@ -5565,6 +5565,7 @@ export default withEnglishFallback({
|
||||
duckDbWorkerProcessIsolationRestartRequired: "Reinicie o DBX para que esta alteração entre em vigor.",
|
||||
restartDbx: "Reiniciar DBX",
|
||||
restartDbxFailed: "Falha ao reiniciar o DBX: {error}",
|
||||
applyFailed: "Falha ao aplicar as configurações: {error}",
|
||||
unsavedChangesCloseTitle: "Alterações não salvas",
|
||||
unsavedChangesCloseMessage: "Você tem alterações de configuração não salvas que serão perdidas se fechar agora. Descartar essas alterações?",
|
||||
unsavedChangesCloseCancel: "Continuar editando",
|
||||
|
||||
@@ -5808,6 +5808,7 @@ export default withEnglishFallback({
|
||||
duckDbWorkerProcessIsolationRestartRequired: "重启 DBX 后生效。",
|
||||
restartDbx: "重启 DBX",
|
||||
restartDbxFailed: "重启 DBX 失败:{error}",
|
||||
applyFailed: "应用设置失败:{error}",
|
||||
unsavedChangesCloseTitle: "未保存的更改",
|
||||
unsavedChangesCloseMessage: "当前设置有未保存的更改,关闭后将丢失。是否放弃这些更改?",
|
||||
unsavedChangesCloseCancel: "继续编辑",
|
||||
|
||||
@@ -4899,6 +4899,7 @@ export default withEnglishFallback({
|
||||
duckDbWorkerProcessIsolationRestartRequired: "重啟 DBX 後生效。",
|
||||
restartDbx: "重啟 DBX",
|
||||
restartDbxFailed: "重啟 DBX 失敗:{error}",
|
||||
applyFailed: "套用設定失敗:{error}",
|
||||
unsavedChangesCloseTitle: "未儲存的變更",
|
||||
unsavedChangesCloseMessage: "目前設定有未儲存的變更,關閉後將遺失。是否放棄這些變更?",
|
||||
unsavedChangesCloseCancel: "繼續編輯",
|
||||
|
||||
Reference in new issue
Block a user