diff --git a/src/installer-message.ts b/src/installer-message.ts index d038d0c..d2c17e7 100644 --- a/src/installer-message.ts +++ b/src/installer-message.ts @@ -26,8 +26,12 @@ export const normalizeInstallSuccessMessage = (message: string): string => ? "Identical to previous version -- not replacing" : "Successful deploy"; +// Both are empty-developer-slot signals: newer devices report "no plugin +// installed", while older ones (e.g. Roku Stick 3500X) fail a delete/replace of +// an empty slot with "No such file or directory". Treating either as an empty +// slot makes delete idempotent and lets a Replace fall back to a fresh Install. export const isEmptyDeveloperSlotMessage = (message: string): boolean => - /no plugin installed/i.test(message); + /no plugin installed/i.test(message) || /no such file or directory/i.test(message); export const isDeleteSuccess = (message: string): boolean => isRecognizedInstallerMessage(message) && diff --git a/test/installer-message.test.ts b/test/installer-message.test.ts new file mode 100644 index 0000000..f50c00f --- /dev/null +++ b/test/installer-message.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from "vite-plus/test"; +import { isDeleteSuccess, isEmptyDeveloperSlotMessage } from "../src/installer-message.js"; + +describe("installer message classification", () => { + it("recognizes both empty developer-slot phrasings", () => { + expect(isEmptyDeveloperSlotMessage("No plugin installed")).toBe(true); + // Older devices fail a delete/replace of an empty slot this way. + expect(isEmptyDeveloperSlotMessage("Delete Failed: No such file or directory")).toBe(true); + expect(isEmptyDeveloperSlotMessage("Some unrelated installer message")).toBe(false); + }); + + it("treats delete success and empty-slot deletes as success, rejects real failures", () => { + expect(isDeleteSuccess("Delete Succeeded.")).toBe(true); + expect(isDeleteSuccess("Delete Failed: No such file or directory")).toBe(true); + expect(isDeleteSuccess("No plugin installed")).toBe(true); + expect(isDeleteSuccess("Install Failure: compilation failed")).toBe(false); + expect(isDeleteSuccess("Empty Roku installer response")).toBe(false); + }); +});