diff --git a/client/src/components/Form/Elements/FormBoolean.test.js b/client/src/components/Form/Elements/FormBoolean.test.js index 29feb654063..16629137fbc 100644 --- a/client/src/components/Form/Elements/FormBoolean.test.js +++ b/client/src/components/Form/Elements/FormBoolean.test.js @@ -19,17 +19,16 @@ describe("FormBoolean", () => { it("check initial value and value change", async () => { const input = wrapper.find("input"); const switchComponent = wrapper.findComponent(".custom-switch"); - expect(switchComponent.props().value).toBe(false); - - await wrapper.setProps({ value: true }); - expect(switchComponent.props().value).toBe(true); - - await input.trigger("click"); - expect(input.element.checked).toBe(false); - - await input.trigger("click"); - expect(input.element.checked).toBe(true); + await wrapper.setProps({ value: "true" }); expect(wrapper.emitted().input[0][0]).toBe(true); + await wrapper.setProps({ value: "false" }); + expect(wrapper.emitted().input[1][0]).toBe(false); + await wrapper.setProps({ value: true }); + expect(wrapper.emitted().input[2][0]).toBe(true); + await input.setChecked(false); + expect(wrapper.emitted().input[3][0]).toBe(false); + await input.setChecked(true); + expect(wrapper.emitted().input[4][0]).toBe(true); }); }); diff --git a/client/src/components/Form/Elements/FormBoolean.vue b/client/src/components/Form/Elements/FormBoolean.vue index e18035db21e..c2a30124d2f 100644 --- a/client/src/components/Form/Elements/FormBoolean.vue +++ b/client/src/components/Form/Elements/FormBoolean.vue @@ -6,14 +6,13 @@ export interface FormBooleanProps { } const props = defineProps(); - const emit = defineEmits<{ (e: "input", value: boolean): void; }>(); const currentValue = computed({ get() { - return Boolean(props.value); + return String(props.value).toLowerCase() === "true"; }, set(newValue) { emit("input", newValue); diff --git a/client/src/components/Form/Elements/FormCheck.test.js b/client/src/components/Form/Elements/FormCheck.test.js index 1279ab1344f..87c2829c6ce 100644 --- a/client/src/components/Form/Elements/FormCheck.test.js +++ b/client/src/components/Form/Elements/FormCheck.test.js @@ -19,32 +19,22 @@ describe("FormCheck", () => { it("Confirm 'n + 1' checkboxes created (eg. includes the Select-All). Confirm labels and values match. Confirm correct values emitted.", async () => { const noInput = wrapper.find("[type='checkbox']"); - expect(noInput.exists()).toBe(false); - const n = 3; const options = []; - for (let i = 0; i < n; i++) { options.push([`label_${i}`, `value_${i}`]); } - await wrapper.setProps({ options }); - const inputs = wrapper.findAll("[type='checkbox']"); const labels = wrapper.findAll(".custom-control-label"); - expect(inputs.length).toBe(n + 1); - const expectedValues = []; - for (let i = 0; i < n; i++) { await inputs.at(i + 1).setChecked(); expect(labels.at(i + 1).text()).toBe(`label_${i}`); expect(inputs.at(i + 1).attributes("value")).toBe(`value_${i}`); - expectedValues.push(`value_${i}`); - expect(wrapper.emitted()["input"][i][0]).toEqual(expectedValues); } }); @@ -52,25 +42,17 @@ describe("FormCheck", () => { it("Confirm checkboxes are created when various 'empty values' are passed.", async () => { const emptyValues = [0, null, false, true, undefined]; const options = []; - for (let i = 0; i < emptyValues.length; i++) { options.push([`label_${i}`, emptyValues[i]]); } - await wrapper.setProps({ options }); - const inputs = wrapper.findAll("[type='checkbox']"); - expect(inputs.length).toBe(emptyValues.length + 1); - const expectedValues = []; - for (let i = 0; i < emptyValues; i++) { await inputs.at(i + 1).setChecked(); expect(inputs.at(i + 1).attributes("value")).toBe(emptyValues[i]); - expectedValues.push(expectedValues[i]); - expect(wrapper.emitted()["input"][i][0]).toEqual(expectedValues); } }); @@ -78,41 +60,30 @@ describe("FormCheck", () => { it("Confirm Select-All checkbox works in various states: select-all, unselect-all, indeterminate/partial-list-selection.", async () => { const n = 3; const options = []; - for (let i = 0; i < n; i++) { options.push([`label_${i}`, `value_${i}`]); } - await wrapper.setProps({ options }); - const inputs = wrapper.findAll("[type='checkbox']"); - /* confirm number of checkboxes requested matches number checkboxes created */ expect(inputs.length).toBe(n + 1); - /* confirm component loads unchecked */ for (let i = 0; i < n + 1; i++) { expect(inputs.at(i).element.checked).toBeFalsy(); } - /* 1 - confirm select-all option checked */ await inputs.at(0).setChecked(); expect(inputs.at(0).element.checked).toBeTruthy(); - /* ...confirm corresponding options checked */ const values = options.map((option) => option[1]); - expect(wrapper.emitted()["input"][0][0]).toStrictEqual(values); - /* 2 - confirm select-all option UNchecked */ await inputs.at(0).setChecked(false); expect(inputs.at(0).element.checked).toBeFalsy(); - /* ...confirm corresponding options UNchecked */ for (let i = 0; i < n; i++) { expect(inputs.at(i + 1).element.checked).toBeFalsy(); } - /* 3 - confirm corresponding options indeterminate-state */ await inputs.at(1).setChecked(true); expect(wrapper.find("input:indeterminate").exists()).toBe(true); diff --git a/lib/galaxy/tools/parameters/basic.py b/lib/galaxy/tools/parameters/basic.py index 4eb129081b3..e84317ff557 100644 --- a/lib/galaxy/tools/parameters/basic.py +++ b/lib/galaxy/tools/parameters/basic.py @@ -542,7 +542,7 @@ class BooleanToolParameter(ToolParameter): >>> p = BooleanToolParameter(None, XML('')) >>> print(p.name) _name - >>> assert sorted(p.to_dict(trans).items()) == [('argument', None), ('falsevalue', '_falsevalue'), ('help', ''), ('hidden', False), ('is_dynamic', False), ('label', ''), ('model_class', 'BooleanToolParameter'), ('name', '_name'), ('optional', False), ('refresh_on_change', False), ('truevalue', '_truevalue'), ('type', 'boolean'), ('value', 'true')] + >>> assert sorted(p.to_dict(trans).items()) == [('argument', None), ('falsevalue', '_falsevalue'), ('help', ''), ('hidden', False), ('is_dynamic', False), ('label', ''), ('model_class', 'BooleanToolParameter'), ('name', '_name'), ('optional', False), ('refresh_on_change', False), ('truevalue', '_truevalue'), ('type', 'boolean'), ('value', True)] >>> print(p.from_json('true')) True >>> print(p.to_param_dict_string(True)) @@ -551,6 +551,12 @@ class BooleanToolParameter(ToolParameter): False >>> print(p.to_param_dict_string(False)) _falsevalue + >>> value = p.to_json('false', trans.app, use_security=False) + >>> assert isinstance(value, bool) + >>> assert value == False + >>> value = p.to_json(True, trans.app, use_security=False) + >>> assert isinstance(value, bool) + >>> assert value == True """ def __init__(self, tool, input_source): @@ -573,8 +579,7 @@ class BooleanToolParameter(ToolParameter): return ret_val def to_json(self, value, app, use_security): - rval = json.dumps(self.to_python(value, app)) - return rval + return self.to_python(value, app) def get_initial_value(self, trans, other_values): return self.checked diff --git a/lib/galaxy/webapps/galaxy/controllers/forms.py b/lib/galaxy/webapps/galaxy/controllers/forms.py index 0d7877bea72..c868f59bdb8 100644 --- a/lib/galaxy/webapps/galaxy/controllers/forms.py +++ b/lib/galaxy/webapps/galaxy/controllers/forms.py @@ -188,7 +188,7 @@ class Forms(BaseUIController): "label": "Options", "help": "*Only for fields which allow multiple selections, provide comma-separated values.", }, - {"name": "required", "label": "Required", "type": "boolean", "value": "false"}, + {"name": "required", "label": "Required", "type": "boolean"}, ] form_dict = { "title": "Edit form for '%s'" % (util.sanitize_text(latest_form.name)),