diff --git a/webclient-vue/src/components/script/ActionScriptsGrid.vue b/webclient-vue/src/components/script/ActionScriptsGrid.vue
index 43a80fa..ef9f74f 100644
--- a/webclient-vue/src/components/script/ActionScriptsGrid.vue
+++ b/webclient-vue/src/components/script/ActionScriptsGrid.vue
@@ -54,6 +54,8 @@
},
});
+const emit = defineEmits(["run-success"]);
+
const router = useRouter();
const scriptsStore = useScriptsStore();
const areasStore = useAreasStore();
@@ -71,6 +73,7 @@
title: `Ran ${alias}`,
text: scriptsStore.lastRunResult?.execTime ? `Exec time: ${scriptsStore.lastRunResult.execTime}` : undefined,
});
+ emit("run-success", { alias });
} else {
toast.error({ title: `Failed ${alias}`, text: result?.error?.message || "Unknown error" });
}
diff --git a/webclient-vue/src/components/script/__tests__/ActionScriptsGrid.spec.js b/webclient-vue/src/components/script/__tests__/ActionScriptsGrid.spec.js
index a3b0953..027596a 100644
--- a/webclient-vue/src/components/script/__tests__/ActionScriptsGrid.spec.js
+++ b/webclient-vue/src/components/script/__tests__/ActionScriptsGrid.spec.js
@@ -2,8 +2,21 @@
import { mount } from "@vue/test-utils";
import { setActivePinia, createPinia } from "pinia";
import { useAreasStore } from "../../../stores/areas.js";
+import { useScriptsStore } from "../../../stores/scripts.js";
import ActionScriptsGrid from "../ActionScriptsGrid.vue";
+vi.mock("gnexus-ui-kit/vue", async () => {
+ const actual = await vi.importActual("gnexus-ui-kit/vue");
+ return {
+ ...actual,
+ useToast: () => ({ success: vi.fn(), error: vi.fn() }),
+ };
+});
+
+vi.mock("vue-router", () => ({
+ useRouter: () => ({ push: vi.fn() }),
+}));
+
describe("ActionScriptsGrid", () => {
beforeEach(() => {
setActivePinia(createPinia());
@@ -66,9 +79,33 @@
expect(wrapper.text()).toContain("Test");
});
- it("emits run event on button click", async () => {
+ it("emits run-success after successful run", async () => {
+ const scriptsStore = useScriptsStore();
+ vi.spyOn(scriptsStore, "runScript").mockResolvedValue({ ok: true });
+ scriptsStore.lastRunResult = { execTime: "0.042 seconds" };
+
const wrapper = createWrapper();
- const buttons = wrapper.findAll("button");
+ const buttons = wrapper.findAll("button").filter((b) => !b.attributes("disabled"));
expect(buttons.length).toBeGreaterThan(0);
+
+ await buttons[0].trigger("click");
+ await new Promise((r) => setTimeout(r, 0)); // flush microtasks
+
+ expect(wrapper.emitted("run-success")).toBeTruthy();
+ expect(wrapper.emitted("run-success")[0]).toEqual([{ alias: "kitchen_light" }]);
+ });
+
+ it("does not emit run-success on failed run", async () => {
+ const scriptsStore = useScriptsStore();
+ vi.spyOn(scriptsStore, "runScript").mockResolvedValue({ ok: false, error: { message: "Boom" } });
+
+ const wrapper = createWrapper();
+ const buttons = wrapper.findAll("button").filter((b) => !b.attributes("disabled"));
+ expect(buttons.length).toBeGreaterThan(0);
+
+ await buttons[0].trigger("click");
+ await new Promise((r) => setTimeout(r, 0));
+
+ expect(wrapper.emitted("run-success")).toBeFalsy();
});
});
diff --git a/webclient-vue/src/features/areas/pages/AreaDetailPage.vue b/webclient-vue/src/features/areas/pages/AreaDetailPage.vue
index f5c7f98..f70eb86 100644
--- a/webclient-vue/src/features/areas/pages/AreaDetailPage.vue
+++ b/webclient-vue/src/features/areas/pages/AreaDetailPage.vue
@@ -36,7 +36,7 @@
title="No actions"
message="No action scripts assigned to this area."
/>
-