import { describe, it, expect, beforeEach, vi } from "vitest";
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());
});
function createWrapper(props = {}) {
return mount(ActionScriptsGrid, {
props: {
scripts: [
{ id: 1, alias: "kitchen_light", name: "Kitchen Light", icon: '<i class="ph ph-lightbulb"></i>', description: "Toggle kitchen", state: "enabled", author: "Test", scope: "KitchenScope", area_id: 1 },
{ id: 2, alias: "hall_light", name: "Hall Light", state: "disabled", author: "Test" },
],
...props,
},
});
}
it("renders action cards for each script", () => {
const wrapper = createWrapper();
expect(wrapper.text()).toContain("Kitchen Light");
expect(wrapper.text()).toContain("Hall Light");
});
it("shows script description when present", () => {
const wrapper = createWrapper();
expect(wrapper.text()).toContain("Toggle kitchen");
});
it("shows state badge with success variant for enabled", () => {
const wrapper = createWrapper();
expect(wrapper.text()).toContain("enabled");
});
it("shows state badge with secondary variant for disabled", () => {
const wrapper = createWrapper();
expect(wrapper.text()).toContain("disabled");
});
it("shows scope badge when present", () => {
const wrapper = createWrapper();
expect(wrapper.text()).toContain("KitchenScope");
});
it("shows area badge when showAreaBadge is true and area exists", () => {
const areasStore = useAreasStore();
areasStore.areas = [{ id: 1, display_name: "Kitchen Area" }];
const wrapper = createWrapper({ showAreaBadge: true });
expect(wrapper.text()).toContain("Kitchen Area");
});
it("does not show area badge when showAreaBadge is false", () => {
const areasStore = useAreasStore();
areasStore.areas = [{ id: 1, display_name: "Kitchen Area" }];
const wrapper = createWrapper({ showAreaBadge: false });
expect(wrapper.text()).not.toContain("Kitchen Area");
});
it("shows author when present", () => {
const wrapper = createWrapper();
expect(wrapper.text()).toContain("Test");
});
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").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();
});
});