mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Add unit tests for FormPickValue component
7 tests covering mode defaults, mode changes, grow-on-connect behavior, and JSON-encoded tool_state from the API. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
999e73c8f3
commit
e26daf4dd5
@@ -0,0 +1,157 @@
|
||||
import { createTestingPinia } from "@pinia/testing";
|
||||
import { getLocalVue } from "@tests/vitest/helpers";
|
||||
import { shallowMount, type Wrapper } from "@vue/test-utils";
|
||||
import { PiniaVuePlugin } from "pinia";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import Vue from "vue";
|
||||
|
||||
import type { Step } from "@/stores/workflowStepStore";
|
||||
|
||||
import FormElement from "@/components/Form/FormElement.vue";
|
||||
|
||||
import FormPickValue from "./FormPickValue.vue";
|
||||
|
||||
const localVue = getLocalVue();
|
||||
localVue.use(PiniaVuePlugin);
|
||||
|
||||
interface EmittedState {
|
||||
mode: string;
|
||||
num_inputs: number;
|
||||
}
|
||||
|
||||
function makeStep(overrides: Partial<Step> = {}): Step {
|
||||
return {
|
||||
id: 0,
|
||||
name: "Pick Value",
|
||||
type: "pick_value",
|
||||
inputs: [],
|
||||
outputs: [{ name: "output", extensions: ["input"], optional: false }],
|
||||
input_connections: {},
|
||||
position: { left: 0, top: 0 },
|
||||
tool_state: { mode: "first_non_null", num_inputs: 2 },
|
||||
workflow_outputs: [],
|
||||
...overrides,
|
||||
} as Step;
|
||||
}
|
||||
|
||||
function mountPickValue(step?: Step): Wrapper<Vue> {
|
||||
return shallowMount(FormPickValue, {
|
||||
propsData: {
|
||||
step: step ?? makeStep(),
|
||||
},
|
||||
localVue,
|
||||
pinia: createTestingPinia({ createSpy: vi.fn }),
|
||||
provide: {
|
||||
workflowId: "mock-workflow",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function getLastEmittedState(wrapper: Wrapper<Vue>): EmittedState {
|
||||
const events = wrapper.emitted().onChange!;
|
||||
return events[events.length - 1]![0] as EmittedState;
|
||||
}
|
||||
|
||||
function getEmittedCount(wrapper: Wrapper<Vue>): number {
|
||||
return wrapper.emitted().onChange!.length;
|
||||
}
|
||||
|
||||
describe("FormPickValue", () => {
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe("mode defaults", () => {
|
||||
it("defaults to first_non_null when tool_state is empty", () => {
|
||||
const wrapper = mountPickValue(makeStep({ tool_state: {} }));
|
||||
const state = getLastEmittedState(wrapper);
|
||||
expect(state.mode).toBe("first_non_null");
|
||||
expect(state.num_inputs).toBe(2);
|
||||
});
|
||||
|
||||
it("preserves mode from tool_state", () => {
|
||||
const wrapper = mountPickValue(makeStep({ tool_state: { mode: "all_non_null", num_inputs: 3 } }));
|
||||
const state = getLastEmittedState(wrapper);
|
||||
expect(state.mode).toBe("all_non_null");
|
||||
expect(state.num_inputs).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe("mode changes", () => {
|
||||
it("emits onChange with updated mode", () => {
|
||||
const wrapper = mountPickValue();
|
||||
const formElement = wrapper.findComponent(FormElement);
|
||||
formElement.vm.$emit("input", "the_only_non_null");
|
||||
|
||||
const state = getLastEmittedState(wrapper);
|
||||
expect(state.mode).toBe("the_only_non_null");
|
||||
expect(state.num_inputs).toBe(2);
|
||||
});
|
||||
|
||||
it("preserves num_inputs when changing mode", () => {
|
||||
const wrapper = mountPickValue(makeStep({ tool_state: { mode: "first_non_null", num_inputs: 5 } }));
|
||||
const formElement = wrapper.findComponent(FormElement);
|
||||
formElement.vm.$emit("input", "all_non_null");
|
||||
|
||||
const state = getLastEmittedState(wrapper);
|
||||
expect(state.mode).toBe("all_non_null");
|
||||
expect(state.num_inputs).toBe(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe("grow-on-connect", () => {
|
||||
it("increments num_inputs when last terminal gets connected", async () => {
|
||||
const step = makeStep({ tool_state: { mode: "first_non_null", num_inputs: 2 } });
|
||||
const wrapper = mountPickValue(step);
|
||||
|
||||
// Simulate connecting to the last empty terminal (input_2, since num_inputs=2)
|
||||
await wrapper.setProps({
|
||||
step: {
|
||||
...step,
|
||||
input_connections: {
|
||||
input_0: [{ id: 1, output_name: "output" }],
|
||||
input_1: [{ id: 2, output_name: "output" }],
|
||||
input_2: [{ id: 3, output_name: "output" }],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(getLastEmittedState(wrapper).num_inputs).toBe(3);
|
||||
});
|
||||
|
||||
it("does not increment when a non-last terminal gets connected", async () => {
|
||||
const step = makeStep({ tool_state: { mode: "first_non_null", num_inputs: 3 } });
|
||||
const wrapper = mountPickValue(step);
|
||||
const countBefore = getEmittedCount(wrapper);
|
||||
|
||||
// Connect to input_1 (not the last terminal input_3)
|
||||
await wrapper.setProps({
|
||||
step: {
|
||||
...step,
|
||||
input_connections: {
|
||||
input_1: [{ id: 2, output_name: "output" }],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(getEmittedCount(wrapper)).toBe(countBefore);
|
||||
});
|
||||
});
|
||||
|
||||
describe("JSON-encoded tool_state", () => {
|
||||
it("handles JSON-string-encoded values from API", () => {
|
||||
// The build_module API may return tool_state values as JSON strings
|
||||
const wrapper = mountPickValue(
|
||||
makeStep({
|
||||
tool_state: {
|
||||
mode: JSON.stringify("the_only_non_null"),
|
||||
num_inputs: JSON.stringify(4),
|
||||
},
|
||||
})
|
||||
);
|
||||
const state = getLastEmittedState(wrapper);
|
||||
expect(state.mode).toBe("the_only_non_null");
|
||||
expect(state.num_inputs).toBe(4);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user