lhcb-ntuple-wizard-test 2.0.7 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.js +2 -1
- package/dist/components/AddTupleToolButton.d.ts +1 -0
- package/dist/components/AddTupleToolButton.js +16 -0
- package/dist/components/BookkeepingPathDropdown.d.ts +1 -1
- package/dist/components/BookkeepingPathDropdown.js +1 -4
- package/dist/components/DatasetEventTypeBadge.js +1 -1
- package/dist/components/DatasetInfo.js +3 -3
- package/dist/components/DecayCard.d.ts +1 -0
- package/dist/components/DecayCard.js +47 -0
- package/dist/components/DecayLatex.d.ts +1 -1
- package/dist/components/DecayLatex.js +4 -87
- package/dist/components/DecayListItem.js +2 -2
- package/dist/components/DecayTagBadge.d.ts +1 -1
- package/dist/components/DecayTagBadge.js +0 -3
- package/dist/components/DecayTreeCard.d.ts +1 -7
- package/dist/components/DecayTreeCard.js +14 -22
- package/dist/components/DecayTreeCardHeader.d.ts +2 -3
- package/dist/components/DecayTreeCardHeader.js +2 -2
- package/dist/components/DecayTreeGraph.d.ts +1 -5
- package/dist/components/DecayTreeGraph.js +160 -49
- package/dist/components/DeleteButton.d.ts +3 -1
- package/dist/components/DeleteButton.js +2 -2
- package/dist/components/DttNameInput.d.ts +9 -1
- package/dist/components/DttNameInput.js +29 -61
- package/dist/components/GuideLinkButton.d.ts +15 -0
- package/dist/components/GuideLinkButton.js +16 -0
- package/dist/components/NtupleWizard.js +1 -2
- package/dist/components/ParticleDropdown.d.ts +11 -1
- package/dist/components/ParticleDropdown.js +3 -6
- package/dist/components/ParticleLatex.d.ts +6 -0
- package/dist/components/ParticleLatex.js +13 -0
- package/dist/components/ParticleTagBadge.d.ts +2 -1
- package/dist/components/ParticleTagBadge.js +5 -7
- package/dist/components/ParticleTagFilters.d.ts +1 -6
- package/dist/components/ParticleTagFilters.js +16 -17
- package/dist/components/RequestButtonGroup.d.ts +1 -1
- package/dist/components/RequestButtonGroup.js +2 -5
- package/dist/components/RequestRow.d.ts +1 -1
- package/dist/components/RequestRow.js +8 -12
- package/dist/components/StrippingLineDropdown.js +14 -16
- package/dist/components/StrippingLineInfo.d.ts +5 -5
- package/dist/components/StrippingLineInfo.js +14 -4
- package/dist/components/StrippingLineInfoButton.d.ts +6 -0
- package/dist/components/StrippingLineInfoButton.js +7 -0
- package/dist/components/StrippingLineVersionBadge.d.ts +7 -0
- package/dist/components/{StrippingLineBadge.js → StrippingLineVersionBadge.js} +5 -5
- package/dist/components/StrippingLinesCountBadge.d.ts +8 -0
- package/dist/components/StrippingLinesCountBadge.js +11 -0
- package/dist/components/TagDropdown.d.ts +3 -3
- package/dist/components/TagDropdown.js +2 -2
- package/dist/components/{TupleToolDropdown.d.ts → TupleToolClassDropdown.d.ts} +2 -5
- package/dist/components/{TupleToolDropdown.js → TupleToolClassDropdown.js} +16 -13
- package/dist/components/TupleToolDocsAccordion.d.ts +1 -1
- package/dist/components/TupleToolDocsAccordion.js +4 -8
- package/dist/components/TupleToolGroupsAccordion.d.ts +5 -0
- package/dist/components/TupleToolGroupsAccordion.js +31 -0
- package/dist/components/TupleToolLabel.d.ts +1 -1
- package/dist/components/TupleToolLabel.js +2 -5
- package/dist/components/TupleToolsAccordion.d.ts +1 -0
- package/dist/components/TupleToolsAccordion.js +22 -0
- package/dist/components/VerticalLine.d.ts +7 -0
- package/dist/components/VerticalLine.js +4 -0
- package/dist/components/modals/AddTupleToolModal.d.ts +3 -4
- package/dist/components/modals/AddTupleToolModal.js +13 -12
- package/dist/components/modals/ConfigureTupleToolModal.d.ts +2 -2
- package/dist/components/modals/ConfigureTupleToolModal.js +28 -11
- package/dist/components/modals/UploadDttConfigModal.d.ts +1 -1
- package/dist/components/modals/UploadDttConfigModal.js +1 -4
- package/dist/config.d.ts +19 -47
- package/dist/config.js +27 -39
- package/dist/models/bkPath.js +1 -1
- package/dist/models/dtt.d.ts +5 -2
- package/dist/models/dtt.js +37 -18
- package/dist/models/rowData.d.ts +1 -1
- package/dist/models/yamlFile.js +1 -1
- package/dist/pages/DecaySearchPage.js +4 -9
- package/dist/pages/DecayTreeConfigPage.js +5 -39
- package/dist/pages/RequestPage.js +11 -16
- package/dist/providers/DttProvider.d.ts +5 -3
- package/dist/providers/DttProvider.js +33 -55
- package/dist/providers/MetadataProvider.d.ts +1 -1
- package/dist/providers/MetadataProvider.js +11 -5
- package/dist/providers/RequestProvider.js +2 -2
- package/dist/providers/RowProvider.d.ts +2 -2
- package/dist/providers/RowProvider.js +10 -9
- package/dist/providers/RowsProvider.js +0 -3
- package/dist/tests/components/BookkeepingPathDropdown.test.d.ts +1 -0
- package/dist/tests/components/BookkeepingPathDropdown.test.js +118 -0
- package/dist/tests/components/DatasetInfo.test.d.ts +1 -0
- package/dist/tests/components/DatasetInfo.test.js +38 -0
- package/dist/tests/components/DecayCard.test.d.ts +1 -0
- package/dist/tests/components/DecayCard.test.js +115 -0
- package/dist/tests/components/DecayLatex.test.d.ts +1 -0
- package/dist/tests/components/DecayLatex.test.js +31 -0
- package/dist/tests/components/DecayList.test.d.ts +1 -0
- package/dist/tests/components/DecayList.test.js +76 -0
- package/dist/tests/components/DecayListItem.test.d.ts +1 -0
- package/dist/tests/components/DecayListItem.test.js +51 -0
- package/dist/tests/components/DecayTreeCard.test.d.ts +1 -0
- package/dist/tests/components/DecayTreeCard.test.js +119 -0
- package/dist/tests/components/DecayTreeGraph.test.d.ts +1 -0
- package/dist/tests/components/DecayTreeGraph.test.js +125 -0
- package/dist/tests/components/DeleteButton.test.d.ts +1 -0
- package/dist/tests/components/DeleteButton.test.js +45 -0
- package/dist/tests/components/DttNameInput.test.d.ts +1 -0
- package/dist/tests/components/DttNameInput.test.js +75 -0
- package/dist/tests/components/NtupleWizard.test.d.ts +1 -0
- package/dist/tests/components/NtupleWizard.test.js +57 -0
- package/dist/tests/components/ParticleDropdown.test.d.ts +1 -0
- package/dist/tests/components/ParticleDropdown.test.js +23 -0
- package/dist/tests/components/ParticleTagFilters.test.d.ts +1 -0
- package/dist/tests/components/ParticleTagFilters.test.js +87 -0
- package/dist/tests/components/RequestButtonGroup.test.d.ts +1 -0
- package/dist/tests/components/RequestButtonGroup.test.js +132 -0
- package/dist/tests/components/RequestRow.test.d.ts +1 -0
- package/dist/tests/components/RequestRow.test.js +58 -0
- package/dist/tests/components/StrippingLineDropdown.test.d.ts +1 -0
- package/dist/tests/components/StrippingLineDropdown.test.js +88 -0
- package/dist/tests/components/badges.test.d.ts +1 -0
- package/dist/tests/components/badges.test.js +120 -0
- package/dist/tests/components/dropdowns.test.d.ts +1 -0
- package/dist/tests/components/dropdowns.test.js +110 -0
- package/dist/tests/components/dttComponents.test.d.ts +1 -0
- package/dist/tests/components/dttComponents.test.js +287 -0
- package/dist/tests/components/formInputs.test.d.ts +1 -0
- package/dist/tests/components/formInputs.test.js +96 -0
- package/dist/tests/components/metadataComponents.test.d.ts +1 -0
- package/dist/tests/components/metadataComponents.test.js +137 -0
- package/dist/tests/components/miscComponents.test.d.ts +1 -0
- package/dist/tests/components/miscComponents.test.js +134 -0
- package/dist/tests/components/modals.test.d.ts +1 -0
- package/dist/tests/components/modals.test.js +554 -0
- package/dist/tests/components/tupleToolParams.test.d.ts +1 -0
- package/dist/tests/components/tupleToolParams.test.js +213 -0
- package/dist/tests/config.test.d.ts +1 -0
- package/dist/tests/config.test.js +31 -0
- package/dist/tests/mockSetup.d.ts +1 -0
- package/dist/tests/mockSetup.js +30 -0
- package/dist/tests/models/BkPath.test.d.ts +1 -0
- package/dist/tests/models/BkPath.test.js +87 -0
- package/dist/tests/models/Dtt.test.d.ts +1 -0
- package/dist/tests/models/Dtt.test.js +376 -0
- package/dist/tests/models/TupleTool.test.d.ts +1 -0
- package/dist/tests/models/TupleTool.test.js +80 -0
- package/dist/tests/models/YamlFile.test.d.ts +1 -0
- package/dist/tests/models/YamlFile.test.js +123 -0
- package/dist/tests/pages/DecaySearchPage.test.d.ts +1 -0
- package/dist/tests/pages/DecaySearchPage.test.js +228 -0
- package/dist/tests/pages/DecayTreeConfigPage.test.d.ts +1 -0
- package/dist/tests/pages/DecayTreeConfigPage.test.js +105 -0
- package/dist/tests/pages/RequestPage.test.d.ts +1 -0
- package/dist/tests/pages/RequestPage.test.js +439 -0
- package/dist/tests/providers/DttProvider.test.d.ts +1 -0
- package/dist/tests/providers/DttProvider.test.js +105 -0
- package/dist/tests/providers/MetadataProvider.test.d.ts +1 -0
- package/dist/tests/providers/MetadataProvider.test.js +129 -0
- package/dist/tests/providers/RequestProvider.test.d.ts +1 -0
- package/dist/tests/providers/RequestProvider.test.js +306 -0
- package/dist/tests/providers/RowProvider.test.d.ts +1 -0
- package/dist/tests/providers/RowProvider.test.js +110 -0
- package/dist/tests/providers/RowsProvider.test.d.ts +1 -0
- package/dist/tests/providers/RowsProvider.test.js +84 -0
- package/dist/tests/providers/WizardConfigProvider.test.d.ts +1 -0
- package/dist/tests/providers/WizardConfigProvider.test.js +36 -0
- package/dist/tests/setupTests.d.ts +1 -0
- package/dist/tests/setupTests.js +15 -0
- package/dist/tests/testUtils.d.ts +33 -0
- package/dist/tests/testUtils.js +196 -0
- package/dist/tests/utils/latexUtils.test.d.ts +1 -0
- package/dist/tests/utils/latexUtils.test.js +62 -0
- package/dist/tests/utils/utils.test.d.ts +1 -0
- package/dist/tests/utils/utils.test.js +394 -0
- package/dist/utils/latexUtils.d.ts +13 -0
- package/dist/utils/latexUtils.js +86 -0
- package/dist/utils/utils.d.ts +1 -0
- package/dist/utils/utils.js +40 -4
- package/package.json +24 -10
- package/dist/components/NumStrippingLinesBadge.d.ts +0 -8
- package/dist/components/NumStrippingLinesBadge.js +0 -10
- package/dist/components/StrippingLineBadge.d.ts +0 -7
- package/dist/components/TupleToolGroup.d.ts +0 -6
- package/dist/components/TupleToolGroup.js +0 -22
- package/dist/components/TupleToolList.d.ts +0 -7
- package/dist/components/TupleToolList.js +0 -38
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import { BoolParamInput } from "../../components/tupleToolParams/BoolParamInput";
|
|
5
|
+
import { StrParamInput, sanitizeStrTupleToolParam } from "../../components/tupleToolParams/StrParamInput";
|
|
6
|
+
import { NumParamInput } from "../../components/tupleToolParams/NumParamInput";
|
|
7
|
+
import { ListParamInput } from "../../components/tupleToolParams/ListParamInput";
|
|
8
|
+
import { DictParamInput } from "../../components/tupleToolParams/DictParamInput";
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// BoolParamInput
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
describe("BoolParamInput", () => {
|
|
13
|
+
it("renders a toggle switch", () => {
|
|
14
|
+
render(_jsx(BoolParamInput, { value: false, onChange: vi.fn() }));
|
|
15
|
+
expect(screen.getByRole("checkbox")).toBeInTheDocument();
|
|
16
|
+
});
|
|
17
|
+
it("reflects the current value (unchecked)", () => {
|
|
18
|
+
render(_jsx(BoolParamInput, { value: false, onChange: vi.fn() }));
|
|
19
|
+
expect(screen.getByRole("checkbox")).not.toBeChecked();
|
|
20
|
+
});
|
|
21
|
+
it("reflects the current value (checked)", () => {
|
|
22
|
+
render(_jsx(BoolParamInput, { value: true, onChange: vi.fn() }));
|
|
23
|
+
expect(screen.getByRole("checkbox")).toBeChecked();
|
|
24
|
+
});
|
|
25
|
+
it("calls onChange with the toggled value when clicked", () => {
|
|
26
|
+
const onChange = vi.fn();
|
|
27
|
+
render(_jsx(BoolParamInput, { value: false, onChange: onChange }));
|
|
28
|
+
fireEvent.click(screen.getByRole("checkbox"));
|
|
29
|
+
expect(onChange).toHaveBeenCalledWith(true);
|
|
30
|
+
});
|
|
31
|
+
it("calls onChange with false when toggling from true", () => {
|
|
32
|
+
const onChange = vi.fn();
|
|
33
|
+
render(_jsx(BoolParamInput, { value: true, onChange: onChange }));
|
|
34
|
+
fireEvent.click(screen.getByRole("checkbox"));
|
|
35
|
+
expect(onChange).toHaveBeenCalledWith(false);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// sanitizeStrTupleToolParam (exported utility)
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
describe("sanitizeStrTupleToolParam()", () => {
|
|
42
|
+
it("allows letters, numbers, underscore, colon, and hyphen", () => {
|
|
43
|
+
expect(sanitizeStrTupleToolParam("abc_123:def-xyz")).toBe("abc_123:def-xyz");
|
|
44
|
+
});
|
|
45
|
+
it("strips spaces", () => {
|
|
46
|
+
expect(sanitizeStrTupleToolParam("hello world")).toBe("helloworld");
|
|
47
|
+
});
|
|
48
|
+
it("strips special characters", () => {
|
|
49
|
+
expect(sanitizeStrTupleToolParam("a!@#b$c")).toBe("abc");
|
|
50
|
+
});
|
|
51
|
+
it("returns empty string for fully disallowed input", () => {
|
|
52
|
+
expect(sanitizeStrTupleToolParam("!@#$")).toBe("");
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// StrParamInput
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
describe("StrParamInput", () => {
|
|
59
|
+
it("renders a text input with the current value", () => {
|
|
60
|
+
render(_jsx(StrParamInput, { value: "hello", onChange: vi.fn() }));
|
|
61
|
+
expect(screen.getByDisplayValue("hello")).toBeInTheDocument();
|
|
62
|
+
});
|
|
63
|
+
it("calls onChange with the sanitized value on change", () => {
|
|
64
|
+
const onChange = vi.fn();
|
|
65
|
+
render(_jsx(StrParamInput, { value: "", onChange: onChange }));
|
|
66
|
+
fireEvent.change(screen.getByRole("textbox"), { target: { value: "valid_value" } });
|
|
67
|
+
expect(onChange).toHaveBeenCalledWith("valid_value");
|
|
68
|
+
});
|
|
69
|
+
it("strips disallowed characters except for ExtraName param", () => {
|
|
70
|
+
const onChange = vi.fn();
|
|
71
|
+
render(_jsx(StrParamInput, { value: "", onChange: onChange }));
|
|
72
|
+
fireEvent.change(screen.getByRole("textbox"), { target: { value: "hello world!" } });
|
|
73
|
+
// Space and ! are stripped by default sanitizer
|
|
74
|
+
expect(onChange).toHaveBeenCalledWith("helloworld");
|
|
75
|
+
});
|
|
76
|
+
it("allows spaces in ExtraName param (only strips non-word chars)", () => {
|
|
77
|
+
const onChange = vi.fn();
|
|
78
|
+
render(_jsx(StrParamInput, { value: "", onChange: onChange, param: "ExtraName" }));
|
|
79
|
+
fireEvent.change(screen.getByRole("textbox"), { target: { value: "My Name" } });
|
|
80
|
+
// ExtraName uses \W replacement, which also removes space
|
|
81
|
+
expect(onChange).toHaveBeenCalledWith("MyName");
|
|
82
|
+
});
|
|
83
|
+
it("shows placeholder from defaultValue", () => {
|
|
84
|
+
render(_jsx(StrParamInput, { value: "", onChange: vi.fn(), defaultValue: "default_val" }));
|
|
85
|
+
expect(screen.getByPlaceholderText("default_val")).toBeInTheDocument();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// NumParamInput
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
describe("NumParamInput", () => {
|
|
92
|
+
it("renders a number input with the current value", () => {
|
|
93
|
+
render(_jsx(NumParamInput, { type: "int", value: 42, onChange: vi.fn() }));
|
|
94
|
+
expect(screen.getByRole("spinbutton")).toHaveValue(42);
|
|
95
|
+
});
|
|
96
|
+
it("calls onChange with the parsed number", () => {
|
|
97
|
+
const onChange = vi.fn();
|
|
98
|
+
render(_jsx(NumParamInput, { type: "float", value: 0, onChange: onChange }));
|
|
99
|
+
fireEvent.change(screen.getByRole("spinbutton"), { target: { value: "3.14" } });
|
|
100
|
+
expect(onChange).toHaveBeenCalledWith(3.14);
|
|
101
|
+
});
|
|
102
|
+
it("truncates float to int for 'int' type", () => {
|
|
103
|
+
const onChange = vi.fn();
|
|
104
|
+
render(_jsx(NumParamInput, { type: "int", value: 0, onChange: onChange }));
|
|
105
|
+
fireEvent.change(screen.getByRole("spinbutton"), { target: { value: "3.7" } });
|
|
106
|
+
expect(onChange).toHaveBeenCalledWith(3);
|
|
107
|
+
});
|
|
108
|
+
it("takes absolute value and truncates for 'uint' type", () => {
|
|
109
|
+
const onChange = vi.fn();
|
|
110
|
+
render(_jsx(NumParamInput, { type: "uint", value: 0, onChange: onChange }));
|
|
111
|
+
fireEvent.change(screen.getByRole("spinbutton"), { target: { value: "-5.9" } });
|
|
112
|
+
expect(onChange).toHaveBeenCalledWith(5);
|
|
113
|
+
});
|
|
114
|
+
it("sets min=0 for uint type", () => {
|
|
115
|
+
render(_jsx(NumParamInput, { type: "uint", value: 0, onChange: vi.fn() }));
|
|
116
|
+
expect(screen.getByRole("spinbutton")).toHaveAttribute("min", "0");
|
|
117
|
+
});
|
|
118
|
+
it("sets step=1 for int type", () => {
|
|
119
|
+
render(_jsx(NumParamInput, { type: "int", value: 0, onChange: vi.fn() }));
|
|
120
|
+
expect(screen.getByRole("spinbutton")).toHaveAttribute("step", "1");
|
|
121
|
+
});
|
|
122
|
+
it("does not set step for float type", () => {
|
|
123
|
+
render(_jsx(NumParamInput, { type: "float", value: 0, onChange: vi.fn() }));
|
|
124
|
+
expect(screen.getByRole("spinbutton")).not.toHaveAttribute("step");
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
// ListParamInput
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
describe("ListParamInput", () => {
|
|
131
|
+
const strInput = ({ value, onChange, defaultValue, }) => _jsx("input", { value: value, onChange: (e) => onChange(e.target.value), placeholder: defaultValue });
|
|
132
|
+
it("renders initial items", () => {
|
|
133
|
+
render(_jsx(ListParamInput, { initialValues: ["a", "b"], defaultValues: [], newItemValue: "", onChange: vi.fn(), buildInnerInput: strInput }));
|
|
134
|
+
expect(screen.getAllByRole("textbox")).toHaveLength(2);
|
|
135
|
+
});
|
|
136
|
+
it("adds a new item when the + button is clicked", () => {
|
|
137
|
+
render(_jsx(ListParamInput, { initialValues: [], defaultValues: [], newItemValue: "new", onChange: vi.fn(), buildInnerInput: strInput }));
|
|
138
|
+
fireEvent.click(screen.getByRole("button"));
|
|
139
|
+
expect(screen.getAllByRole("textbox")).toHaveLength(1);
|
|
140
|
+
});
|
|
141
|
+
it("uses defaultValues for new items when available", () => {
|
|
142
|
+
render(_jsx(ListParamInput, { initialValues: [], defaultValues: ["default1", "default2"], newItemValue: "", onChange: vi.fn(), buildInnerInput: strInput }));
|
|
143
|
+
fireEvent.click(screen.getByRole("button"));
|
|
144
|
+
expect(screen.getByDisplayValue("default1")).toBeInTheDocument();
|
|
145
|
+
});
|
|
146
|
+
it("removes an item when its close button is clicked", () => {
|
|
147
|
+
render(_jsx(ListParamInput, { initialValues: ["a", "b"], defaultValues: [], newItemValue: "", onChange: vi.fn(), buildInnerInput: strInput }));
|
|
148
|
+
const closeButtons = screen.getAllByRole("button", { name: /close/i });
|
|
149
|
+
fireEvent.click(closeButtons[0]);
|
|
150
|
+
expect(screen.getAllByRole("textbox")).toHaveLength(1);
|
|
151
|
+
});
|
|
152
|
+
it("calls onChange when an item is removed", () => {
|
|
153
|
+
const onChange = vi.fn();
|
|
154
|
+
render(_jsx(ListParamInput, { initialValues: ["a", "b"], defaultValues: [], newItemValue: "", onChange: onChange, buildInnerInput: strInput }));
|
|
155
|
+
fireEvent.click(screen.getAllByRole("button", { name: /close/i })[0]);
|
|
156
|
+
expect(onChange).toHaveBeenCalledWith(["b"]);
|
|
157
|
+
});
|
|
158
|
+
it("calls onChange when an existing item value is changed", () => {
|
|
159
|
+
const onChange = vi.fn();
|
|
160
|
+
render(_jsx(ListParamInput, { initialValues: ["a", "b"], defaultValues: [], newItemValue: "", onChange: onChange, buildInnerInput: strInput }));
|
|
161
|
+
const inputs = screen.getAllByRole("textbox");
|
|
162
|
+
fireEvent.change(inputs[0], { target: { value: "z" } });
|
|
163
|
+
expect(onChange).toHaveBeenCalledWith(["z", "b"]);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
// DictParamInput
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
describe("DictParamInput", () => {
|
|
170
|
+
it("renders the JSON value in a textarea", () => {
|
|
171
|
+
const value = { key1: "val1" };
|
|
172
|
+
render(_jsx(DictParamInput, { value: value, onChange: vi.fn() }));
|
|
173
|
+
const textarea = screen.getByRole("textbox");
|
|
174
|
+
expect(textarea).toHaveValue(JSON.stringify(value, null, 2));
|
|
175
|
+
});
|
|
176
|
+
it("textarea is disabled by default (not in edit mode)", () => {
|
|
177
|
+
render(_jsx(DictParamInput, { value: {}, onChange: vi.fn() }));
|
|
178
|
+
expect(screen.getByRole("textbox")).toBeDisabled();
|
|
179
|
+
});
|
|
180
|
+
it("enables textarea after clicking Edit", () => {
|
|
181
|
+
render(_jsx(DictParamInput, { value: {}, onChange: vi.fn() }));
|
|
182
|
+
fireEvent.click(screen.getByText("Edit"));
|
|
183
|
+
expect(screen.getByRole("textbox")).not.toBeDisabled();
|
|
184
|
+
});
|
|
185
|
+
it("shows Save and Cancel buttons in edit mode", () => {
|
|
186
|
+
render(_jsx(DictParamInput, { value: {}, onChange: vi.fn() }));
|
|
187
|
+
fireEvent.click(screen.getByText("Edit"));
|
|
188
|
+
expect(screen.getByText("Save")).toBeInTheDocument();
|
|
189
|
+
expect(screen.getByText("Cancel")).toBeInTheDocument();
|
|
190
|
+
});
|
|
191
|
+
it("calls onChange with parsed JSON on Save", () => {
|
|
192
|
+
const onChange = vi.fn();
|
|
193
|
+
render(_jsx(DictParamInput, { value: {}, onChange: onChange }));
|
|
194
|
+
fireEvent.click(screen.getByText("Edit"));
|
|
195
|
+
fireEvent.change(screen.getByRole("textbox"), { target: { value: '{"a":"b"}' } });
|
|
196
|
+
fireEvent.click(screen.getByText("Save"));
|
|
197
|
+
expect(onChange).toHaveBeenCalledWith({ a: "b" });
|
|
198
|
+
});
|
|
199
|
+
it("shows an error alert for invalid JSON", () => {
|
|
200
|
+
render(_jsx(DictParamInput, { value: {}, onChange: vi.fn() }));
|
|
201
|
+
fireEvent.click(screen.getByText("Edit"));
|
|
202
|
+
fireEvent.change(screen.getByRole("textbox"), { target: { value: "not json" } });
|
|
203
|
+
fireEvent.click(screen.getByText("Save"));
|
|
204
|
+
expect(screen.getByText("Invalid JSON")).toBeInTheDocument();
|
|
205
|
+
});
|
|
206
|
+
it("exits edit mode and hides Save after Cancel", () => {
|
|
207
|
+
render(_jsx(DictParamInput, { value: {}, onChange: vi.fn() }));
|
|
208
|
+
fireEvent.click(screen.getByText("Edit"));
|
|
209
|
+
fireEvent.click(screen.getByText("Cancel"));
|
|
210
|
+
expect(screen.queryByText("Save")).not.toBeInTheDocument();
|
|
211
|
+
expect(screen.getByRole("textbox")).toBeDisabled();
|
|
212
|
+
});
|
|
213
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { config } from "../config";
|
|
3
|
+
// Build a minimal ToolConfig for LoKi__Hybrid__TupleTool with the four variable dicts
|
|
4
|
+
function makeLoKiConfig(variables = {}, boolVariables = {}, floatVariables = {}, intVariables = {}) {
|
|
5
|
+
const asParam = (value) => ({ value, name: "", type: "dict" });
|
|
6
|
+
return {
|
|
7
|
+
Variables: asParam(variables),
|
|
8
|
+
BoolVariables: asParam(boolVariables),
|
|
9
|
+
FloatVariables: asParam(floatVariables),
|
|
10
|
+
IntVariables: asParam(intVariables),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
describe("config.tupleToolValidation — LoKi__Hybrid__TupleTool", () => {
|
|
14
|
+
const validate = config.tupleToolValidation["LoKi__Hybrid__TupleTool"].validate;
|
|
15
|
+
it("returns null when Variables has at least one entry", () => {
|
|
16
|
+
expect(validate(makeLoKiConfig({ PT: "PT" }))).toBeNull();
|
|
17
|
+
});
|
|
18
|
+
it("returns null when only BoolVariables has entries", () => {
|
|
19
|
+
expect(validate(makeLoKiConfig({}, { isPion: "ISBASIC" }))).toBeNull();
|
|
20
|
+
});
|
|
21
|
+
it("returns null when only FloatVariables has entries", () => {
|
|
22
|
+
expect(validate(makeLoKiConfig({}, {}, { mass: "M" }))).toBeNull();
|
|
23
|
+
});
|
|
24
|
+
it("returns null when only IntVariables has entries", () => {
|
|
25
|
+
expect(validate(makeLoKiConfig({}, {}, {}, { charge: "Q" }))).toBeNull();
|
|
26
|
+
});
|
|
27
|
+
it("returns an error message when all variable dicts are empty", () => {
|
|
28
|
+
const result = validate(makeLoKiConfig());
|
|
29
|
+
expect(result).toBe("Please add at least one variable");
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { vi } from "vitest";
|
|
3
|
+
import { mockMetadata } from "./testUtils";
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// MetadataProvider — the most widely mocked module.
|
|
6
|
+
// useMetadata returns the shared mockMetadata fixture.
|
|
7
|
+
// MetadataProvider is stubbed as a passthrough so component tree tests work.
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
vi.mock("../providers/MetadataProvider", () => ({
|
|
10
|
+
useMetadata: () => mockMetadata,
|
|
11
|
+
MetadataProvider: ({ children }) => _jsx(_Fragment, { children: children }),
|
|
12
|
+
}));
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// react-katex — InlineMath renders as a plain span in jsdom
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
vi.mock("react-katex", () => ({
|
|
17
|
+
InlineMath: ({ math }) => _jsx("span", { "data-testid": "inline-math", children: math }),
|
|
18
|
+
}));
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// GuideLinkButton — always a simple anchor stub
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
vi.mock("../components/GuideLinkButton", () => ({
|
|
23
|
+
GuideLinkButton: () => _jsx("a", { "data-testid": "guide-link" }),
|
|
24
|
+
}));
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// LoadingIndicator — always a simple div stub
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
vi.mock("../components/LoadingIndicator", () => ({
|
|
29
|
+
LoadingIndicator: () => _jsx("div", { "data-testid": "loading-indicator" }),
|
|
30
|
+
}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { BkPath } from "../../models/bkPath";
|
|
3
|
+
// A valid 9-segment LHCb path (LHCb_PATH_LENGTH = 9)
|
|
4
|
+
const VALID_LHCB_PATH = "/LHCb/Collision16/Beam6500GeV-VeloClosed-MagDown/Real Data/Reco16/Stripping28r2/90000000/DIMUON.DST";
|
|
5
|
+
// The same path but MagUp
|
|
6
|
+
const VALID_LHCB_PATH_MAGUP = "/LHCb/Collision16/Beam6500GeV-VeloClosed-MagUp/Real Data/Reco16/Stripping28r2/90000000/DIMUON.DST";
|
|
7
|
+
// A valid 10-segment MC path (MC_PATH_LENGTH = 10)
|
|
8
|
+
const VALID_MC_PATH = "/MC/2016/Beam6500GeV-VeloClosed-MagDown/Nu6.3-25ns-Pythia8/Sim09b/Trig0x6139160F/Stripping28r2/23103101/ALLSTREAMS.DST";
|
|
9
|
+
// MC path where year is in "Collision" format
|
|
10
|
+
const VALID_MC_PATH_COLLISION_YEAR = "/MC/Collision16/Beam6500GeV-VeloClosed-MagDown/Nu6.3-25ns-Pythia8/Sim09b/Trig0x6139160F/Stripping28r2/23103101/ALLSTREAMS.DST";
|
|
11
|
+
describe("BkPath", () => {
|
|
12
|
+
describe("valid LHCb paths", () => {
|
|
13
|
+
it("parses the year from Collision format", () => {
|
|
14
|
+
expect(new BkPath(VALID_LHCB_PATH).year).toBe("2016");
|
|
15
|
+
});
|
|
16
|
+
it("parses the stripping version", () => {
|
|
17
|
+
expect(new BkPath(VALID_LHCB_PATH).strippingVersion).toBe("28r2");
|
|
18
|
+
});
|
|
19
|
+
it("parses MagDown polarity", () => {
|
|
20
|
+
expect(new BkPath(VALID_LHCB_PATH).polarity).toBe("MagDown");
|
|
21
|
+
});
|
|
22
|
+
it("parses MagUp polarity", () => {
|
|
23
|
+
expect(new BkPath(VALID_LHCB_PATH_MAGUP).polarity).toBe("MagUp");
|
|
24
|
+
});
|
|
25
|
+
it("parses the event type", () => {
|
|
26
|
+
expect(new BkPath(VALID_LHCB_PATH).eventType).toBe("90000000");
|
|
27
|
+
});
|
|
28
|
+
it("parses the file name", () => {
|
|
29
|
+
expect(new BkPath(VALID_LHCB_PATH).fileName).toBe("DIMUON.DST");
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe("valid MC paths", () => {
|
|
33
|
+
it("parses a plain year (e.g. 2016)", () => {
|
|
34
|
+
expect(new BkPath(VALID_MC_PATH).year).toBe("2016");
|
|
35
|
+
});
|
|
36
|
+
it("parses the year from Collision format in an MC path", () => {
|
|
37
|
+
expect(new BkPath(VALID_MC_PATH_COLLISION_YEAR).year).toBe("2016");
|
|
38
|
+
});
|
|
39
|
+
it("parses the stripping version", () => {
|
|
40
|
+
expect(new BkPath(VALID_MC_PATH).strippingVersion).toBe("28r2");
|
|
41
|
+
});
|
|
42
|
+
it("parses MagDown polarity from an MC path", () => {
|
|
43
|
+
expect(new BkPath(VALID_MC_PATH).polarity).toBe("MagDown");
|
|
44
|
+
});
|
|
45
|
+
it("parses the event type", () => {
|
|
46
|
+
expect(new BkPath(VALID_MC_PATH).eventType).toBe("23103101");
|
|
47
|
+
});
|
|
48
|
+
it("parses the file name", () => {
|
|
49
|
+
expect(new BkPath(VALID_MC_PATH).fileName).toBe("ALLSTREAMS.DST");
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe("NoPrescalingFlagged stripping version", () => {
|
|
53
|
+
it("strips NoPrescalingFlagged suffix from stripping version", () => {
|
|
54
|
+
const path = "/LHCb/Collision16/Beam6500GeV-VeloClosed-MagDown/Real Data/Reco16/Stripping28r2NoPrescalingFlagged/90000000/DIMUON.DST";
|
|
55
|
+
expect(new BkPath(path).strippingVersion).toBe("28r2");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe("polarity edge cases", () => {
|
|
59
|
+
it("returns null when neither MagUp nor MagDown appears in path", () => {
|
|
60
|
+
const pathNoPolarity = "/LHCb/Collision16/Beam6500GeV-VeloClosed-NoMag/Real Data/Reco16/Stripping28r2/90000000/DIMUON.DST";
|
|
61
|
+
expect(new BkPath(pathNoPolarity).polarity).toBeNull();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe("invalid paths — must throw", () => {
|
|
65
|
+
it("throws when path does not start with /", () => {
|
|
66
|
+
expect(() => new BkPath("LHCb/Collision16/Beam6500GeV-VeloClosed-MagDown/Real Data/Reco16/Stripping28r2/90000000/DIMUON.DST")).toThrow();
|
|
67
|
+
});
|
|
68
|
+
it("throws when path does not end with DST (case-insensitive)", () => {
|
|
69
|
+
expect(() => new BkPath("/LHCb/Collision16/Beam6500GeV-VeloClosed-MagDown/Real Data/Reco16/Stripping28r2/90000000/DIMUON.ROOT")).toThrow();
|
|
70
|
+
});
|
|
71
|
+
it("throws for an LHCb path with too few segments", () => {
|
|
72
|
+
expect(() => new BkPath("/LHCb/Collision16/MagDown/Stripping28r2/90000000/DIMUON.DST")).toThrow();
|
|
73
|
+
});
|
|
74
|
+
it("throws for an LHCb path with too many segments", () => {
|
|
75
|
+
expect(() => new BkPath("/LHCb/Collision16/Beam6500GeV-VeloClosed-MagDown/Real Data/Reco16/Extra/Stripping28r2/90000000/DIMUON.DST")).toThrow();
|
|
76
|
+
});
|
|
77
|
+
it("throws for an MC path with too few segments", () => {
|
|
78
|
+
expect(() => new BkPath("/MC/2016/MagDown/Stripping28r2/23103101/ALLSTREAMS.DST")).toThrow();
|
|
79
|
+
});
|
|
80
|
+
it("throws for an unrecognised type prefix", () => {
|
|
81
|
+
expect(() => new BkPath("/Other/Collision16/Beam6500GeV-VeloClosed-MagDown/Real Data/Reco16/Stripping28r2/90000000/DIMUON.DST")).toThrow();
|
|
82
|
+
});
|
|
83
|
+
it("throws for an empty string", () => {
|
|
84
|
+
expect(() => new BkPath("")).toThrow();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|