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.
Files changed (184) hide show
  1. package/dist/App.js +2 -1
  2. package/dist/components/AddTupleToolButton.d.ts +1 -0
  3. package/dist/components/AddTupleToolButton.js +16 -0
  4. package/dist/components/BookkeepingPathDropdown.d.ts +1 -1
  5. package/dist/components/BookkeepingPathDropdown.js +1 -4
  6. package/dist/components/DatasetEventTypeBadge.js +1 -1
  7. package/dist/components/DatasetInfo.js +3 -3
  8. package/dist/components/DecayCard.d.ts +1 -0
  9. package/dist/components/DecayCard.js +47 -0
  10. package/dist/components/DecayLatex.d.ts +1 -1
  11. package/dist/components/DecayLatex.js +4 -87
  12. package/dist/components/DecayListItem.js +2 -2
  13. package/dist/components/DecayTagBadge.d.ts +1 -1
  14. package/dist/components/DecayTagBadge.js +0 -3
  15. package/dist/components/DecayTreeCard.d.ts +1 -7
  16. package/dist/components/DecayTreeCard.js +14 -22
  17. package/dist/components/DecayTreeCardHeader.d.ts +2 -3
  18. package/dist/components/DecayTreeCardHeader.js +2 -2
  19. package/dist/components/DecayTreeGraph.d.ts +1 -5
  20. package/dist/components/DecayTreeGraph.js +160 -49
  21. package/dist/components/DeleteButton.d.ts +3 -1
  22. package/dist/components/DeleteButton.js +2 -2
  23. package/dist/components/DttNameInput.d.ts +9 -1
  24. package/dist/components/DttNameInput.js +29 -61
  25. package/dist/components/GuideLinkButton.d.ts +15 -0
  26. package/dist/components/GuideLinkButton.js +16 -0
  27. package/dist/components/NtupleWizard.js +1 -2
  28. package/dist/components/ParticleDropdown.d.ts +11 -1
  29. package/dist/components/ParticleDropdown.js +3 -6
  30. package/dist/components/ParticleLatex.d.ts +6 -0
  31. package/dist/components/ParticleLatex.js +13 -0
  32. package/dist/components/ParticleTagBadge.d.ts +2 -1
  33. package/dist/components/ParticleTagBadge.js +5 -7
  34. package/dist/components/ParticleTagFilters.d.ts +1 -6
  35. package/dist/components/ParticleTagFilters.js +16 -17
  36. package/dist/components/RequestButtonGroup.d.ts +1 -1
  37. package/dist/components/RequestButtonGroup.js +2 -5
  38. package/dist/components/RequestRow.d.ts +1 -1
  39. package/dist/components/RequestRow.js +8 -12
  40. package/dist/components/StrippingLineDropdown.js +14 -16
  41. package/dist/components/StrippingLineInfo.d.ts +5 -5
  42. package/dist/components/StrippingLineInfo.js +14 -4
  43. package/dist/components/StrippingLineInfoButton.d.ts +6 -0
  44. package/dist/components/StrippingLineInfoButton.js +7 -0
  45. package/dist/components/StrippingLineVersionBadge.d.ts +7 -0
  46. package/dist/components/{StrippingLineBadge.js → StrippingLineVersionBadge.js} +5 -5
  47. package/dist/components/StrippingLinesCountBadge.d.ts +8 -0
  48. package/dist/components/StrippingLinesCountBadge.js +11 -0
  49. package/dist/components/TagDropdown.d.ts +3 -3
  50. package/dist/components/TagDropdown.js +2 -2
  51. package/dist/components/{TupleToolDropdown.d.ts → TupleToolClassDropdown.d.ts} +2 -5
  52. package/dist/components/{TupleToolDropdown.js → TupleToolClassDropdown.js} +16 -13
  53. package/dist/components/TupleToolDocsAccordion.d.ts +1 -1
  54. package/dist/components/TupleToolDocsAccordion.js +4 -8
  55. package/dist/components/TupleToolGroupsAccordion.d.ts +5 -0
  56. package/dist/components/TupleToolGroupsAccordion.js +31 -0
  57. package/dist/components/TupleToolLabel.d.ts +1 -1
  58. package/dist/components/TupleToolLabel.js +2 -5
  59. package/dist/components/TupleToolsAccordion.d.ts +1 -0
  60. package/dist/components/TupleToolsAccordion.js +22 -0
  61. package/dist/components/VerticalLine.d.ts +7 -0
  62. package/dist/components/VerticalLine.js +4 -0
  63. package/dist/components/modals/AddTupleToolModal.d.ts +3 -4
  64. package/dist/components/modals/AddTupleToolModal.js +13 -12
  65. package/dist/components/modals/ConfigureTupleToolModal.d.ts +2 -2
  66. package/dist/components/modals/ConfigureTupleToolModal.js +28 -11
  67. package/dist/components/modals/UploadDttConfigModal.d.ts +1 -1
  68. package/dist/components/modals/UploadDttConfigModal.js +1 -4
  69. package/dist/config.d.ts +19 -47
  70. package/dist/config.js +27 -39
  71. package/dist/models/bkPath.js +1 -1
  72. package/dist/models/dtt.d.ts +5 -2
  73. package/dist/models/dtt.js +37 -18
  74. package/dist/models/rowData.d.ts +1 -1
  75. package/dist/models/yamlFile.js +1 -1
  76. package/dist/pages/DecaySearchPage.js +4 -9
  77. package/dist/pages/DecayTreeConfigPage.js +5 -39
  78. package/dist/pages/RequestPage.js +11 -16
  79. package/dist/providers/DttProvider.d.ts +5 -3
  80. package/dist/providers/DttProvider.js +33 -55
  81. package/dist/providers/MetadataProvider.d.ts +1 -1
  82. package/dist/providers/MetadataProvider.js +11 -5
  83. package/dist/providers/RequestProvider.js +2 -2
  84. package/dist/providers/RowProvider.d.ts +2 -2
  85. package/dist/providers/RowProvider.js +10 -9
  86. package/dist/providers/RowsProvider.js +0 -3
  87. package/dist/tests/components/BookkeepingPathDropdown.test.d.ts +1 -0
  88. package/dist/tests/components/BookkeepingPathDropdown.test.js +118 -0
  89. package/dist/tests/components/DatasetInfo.test.d.ts +1 -0
  90. package/dist/tests/components/DatasetInfo.test.js +38 -0
  91. package/dist/tests/components/DecayCard.test.d.ts +1 -0
  92. package/dist/tests/components/DecayCard.test.js +115 -0
  93. package/dist/tests/components/DecayLatex.test.d.ts +1 -0
  94. package/dist/tests/components/DecayLatex.test.js +31 -0
  95. package/dist/tests/components/DecayList.test.d.ts +1 -0
  96. package/dist/tests/components/DecayList.test.js +76 -0
  97. package/dist/tests/components/DecayListItem.test.d.ts +1 -0
  98. package/dist/tests/components/DecayListItem.test.js +51 -0
  99. package/dist/tests/components/DecayTreeCard.test.d.ts +1 -0
  100. package/dist/tests/components/DecayTreeCard.test.js +119 -0
  101. package/dist/tests/components/DecayTreeGraph.test.d.ts +1 -0
  102. package/dist/tests/components/DecayTreeGraph.test.js +125 -0
  103. package/dist/tests/components/DeleteButton.test.d.ts +1 -0
  104. package/dist/tests/components/DeleteButton.test.js +45 -0
  105. package/dist/tests/components/DttNameInput.test.d.ts +1 -0
  106. package/dist/tests/components/DttNameInput.test.js +75 -0
  107. package/dist/tests/components/NtupleWizard.test.d.ts +1 -0
  108. package/dist/tests/components/NtupleWizard.test.js +57 -0
  109. package/dist/tests/components/ParticleDropdown.test.d.ts +1 -0
  110. package/dist/tests/components/ParticleDropdown.test.js +23 -0
  111. package/dist/tests/components/ParticleTagFilters.test.d.ts +1 -0
  112. package/dist/tests/components/ParticleTagFilters.test.js +87 -0
  113. package/dist/tests/components/RequestButtonGroup.test.d.ts +1 -0
  114. package/dist/tests/components/RequestButtonGroup.test.js +132 -0
  115. package/dist/tests/components/RequestRow.test.d.ts +1 -0
  116. package/dist/tests/components/RequestRow.test.js +58 -0
  117. package/dist/tests/components/StrippingLineDropdown.test.d.ts +1 -0
  118. package/dist/tests/components/StrippingLineDropdown.test.js +88 -0
  119. package/dist/tests/components/badges.test.d.ts +1 -0
  120. package/dist/tests/components/badges.test.js +120 -0
  121. package/dist/tests/components/dropdowns.test.d.ts +1 -0
  122. package/dist/tests/components/dropdowns.test.js +110 -0
  123. package/dist/tests/components/dttComponents.test.d.ts +1 -0
  124. package/dist/tests/components/dttComponents.test.js +287 -0
  125. package/dist/tests/components/formInputs.test.d.ts +1 -0
  126. package/dist/tests/components/formInputs.test.js +96 -0
  127. package/dist/tests/components/metadataComponents.test.d.ts +1 -0
  128. package/dist/tests/components/metadataComponents.test.js +137 -0
  129. package/dist/tests/components/miscComponents.test.d.ts +1 -0
  130. package/dist/tests/components/miscComponents.test.js +134 -0
  131. package/dist/tests/components/modals.test.d.ts +1 -0
  132. package/dist/tests/components/modals.test.js +554 -0
  133. package/dist/tests/components/tupleToolParams.test.d.ts +1 -0
  134. package/dist/tests/components/tupleToolParams.test.js +213 -0
  135. package/dist/tests/config.test.d.ts +1 -0
  136. package/dist/tests/config.test.js +31 -0
  137. package/dist/tests/mockSetup.d.ts +1 -0
  138. package/dist/tests/mockSetup.js +30 -0
  139. package/dist/tests/models/BkPath.test.d.ts +1 -0
  140. package/dist/tests/models/BkPath.test.js +87 -0
  141. package/dist/tests/models/Dtt.test.d.ts +1 -0
  142. package/dist/tests/models/Dtt.test.js +376 -0
  143. package/dist/tests/models/TupleTool.test.d.ts +1 -0
  144. package/dist/tests/models/TupleTool.test.js +80 -0
  145. package/dist/tests/models/YamlFile.test.d.ts +1 -0
  146. package/dist/tests/models/YamlFile.test.js +123 -0
  147. package/dist/tests/pages/DecaySearchPage.test.d.ts +1 -0
  148. package/dist/tests/pages/DecaySearchPage.test.js +228 -0
  149. package/dist/tests/pages/DecayTreeConfigPage.test.d.ts +1 -0
  150. package/dist/tests/pages/DecayTreeConfigPage.test.js +105 -0
  151. package/dist/tests/pages/RequestPage.test.d.ts +1 -0
  152. package/dist/tests/pages/RequestPage.test.js +439 -0
  153. package/dist/tests/providers/DttProvider.test.d.ts +1 -0
  154. package/dist/tests/providers/DttProvider.test.js +105 -0
  155. package/dist/tests/providers/MetadataProvider.test.d.ts +1 -0
  156. package/dist/tests/providers/MetadataProvider.test.js +129 -0
  157. package/dist/tests/providers/RequestProvider.test.d.ts +1 -0
  158. package/dist/tests/providers/RequestProvider.test.js +306 -0
  159. package/dist/tests/providers/RowProvider.test.d.ts +1 -0
  160. package/dist/tests/providers/RowProvider.test.js +110 -0
  161. package/dist/tests/providers/RowsProvider.test.d.ts +1 -0
  162. package/dist/tests/providers/RowsProvider.test.js +84 -0
  163. package/dist/tests/providers/WizardConfigProvider.test.d.ts +1 -0
  164. package/dist/tests/providers/WizardConfigProvider.test.js +36 -0
  165. package/dist/tests/setupTests.d.ts +1 -0
  166. package/dist/tests/setupTests.js +15 -0
  167. package/dist/tests/testUtils.d.ts +33 -0
  168. package/dist/tests/testUtils.js +196 -0
  169. package/dist/tests/utils/latexUtils.test.d.ts +1 -0
  170. package/dist/tests/utils/latexUtils.test.js +62 -0
  171. package/dist/tests/utils/utils.test.d.ts +1 -0
  172. package/dist/tests/utils/utils.test.js +394 -0
  173. package/dist/utils/latexUtils.d.ts +13 -0
  174. package/dist/utils/latexUtils.js +86 -0
  175. package/dist/utils/utils.d.ts +1 -0
  176. package/dist/utils/utils.js +40 -4
  177. package/package.json +24 -10
  178. package/dist/components/NumStrippingLinesBadge.d.ts +0 -8
  179. package/dist/components/NumStrippingLinesBadge.js +0 -10
  180. package/dist/components/StrippingLineBadge.d.ts +0 -7
  181. package/dist/components/TupleToolGroup.d.ts +0 -6
  182. package/dist/components/TupleToolGroup.js +0 -22
  183. package/dist/components/TupleToolList.d.ts +0 -7
  184. package/dist/components/TupleToolList.js +0 -38
@@ -0,0 +1,228 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
4
+ import { DecaySearchPage } from "../../pages/DecaySearchPage";
5
+ import { MemoryRouter } from "react-router-dom";
6
+ import { createMockRow, mockDecay } from "../testUtils";
7
+ // ---------------------------------------------------------------------------
8
+ // Provider mocks
9
+ // ---------------------------------------------------------------------------
10
+ let mockRows = [];
11
+ const mockSetRows = vi.fn();
12
+ vi.mock("../../providers/RowsProvider", () => ({
13
+ useRows: () => ({
14
+ rows: mockRows,
15
+ configuredRows: [],
16
+ setRows: mockSetRows,
17
+ updateRow: vi.fn(),
18
+ removeRow: vi.fn(),
19
+ generateAllFiles: vi.fn(),
20
+ }),
21
+ }));
22
+ vi.mock("../../providers/WizardConfigProvider", () => ({
23
+ useWizardConfig: () => ({ variant: "standalone", basePath: "" }),
24
+ }));
25
+ // ---------------------------------------------------------------------------
26
+ // Child component mocks — replace heavy components with lightweight stubs
27
+ // ---------------------------------------------------------------------------
28
+ // Stub DecayList: clicking an unselected item selects it; clicking a selected item deselects it
29
+ vi.mock("../../components/DecayList", () => ({
30
+ DecayList: ({ decays, selectedDecays, onItemSelected, }) => (_jsx("ul", { "data-testid": "decay-list", children: decays.map((d) => {
31
+ const isSelected = selectedDecays.some((sd) => sd.descriptors.plain === d.descriptors.plain);
32
+ return (_jsx("li", { "data-testid": "decay-list-item", "data-selected": isSelected, onClick: () => isSelected
33
+ ? onItemSelected(selectedDecays.filter((sd) => sd.descriptors.plain !== d.descriptors.plain))
34
+ : onItemSelected([...selectedDecays, d]), children: d.descriptors.plain }, d.descriptors.plain));
35
+ }) })),
36
+ }));
37
+ vi.mock("../../components/ParticleDropdown", () => ({
38
+ ParticleDropdown: ({ placeholder }) => (_jsx("input", { "data-testid": "particle-dropdown", placeholder: placeholder })),
39
+ }));
40
+ vi.mock("../../components/TagDropdown", () => ({
41
+ TagDropdown: ({ placeholder }) => (_jsx("input", { "data-testid": "tag-dropdown", placeholder: placeholder })),
42
+ // Keep the real getSelectTagOptions so the useEffect that sets selectedTags works correctly
43
+ getSelectTagOptions: (tags, filter) => Object.keys(tags)
44
+ .filter((k) => filter(tags[k]))
45
+ .map((k) => ({ value: k, label: k })),
46
+ }));
47
+ // Make useTransition fire synchronously so showDecaysList=true immediately
48
+ vi.mock("react", async (importOriginal) => {
49
+ const actual = await importOriginal();
50
+ return {
51
+ ...actual,
52
+ useTransition: () => [false, (fn) => fn()],
53
+ };
54
+ });
55
+ // ---------------------------------------------------------------------------
56
+ // Helpers
57
+ // ---------------------------------------------------------------------------
58
+ function renderPage() {
59
+ return render(_jsx(MemoryRouter, { children: _jsx(DecaySearchPage, {}) }));
60
+ }
61
+ // Wait for the tag-loading effect to run so the decay list is visible
62
+ async function renderPageReady() {
63
+ const result = renderPage();
64
+ await waitFor(() => expect(screen.queryByTestId("loading-indicator")).not.toBeInTheDocument());
65
+ return result;
66
+ }
67
+ // ---------------------------------------------------------------------------
68
+ // Tests — structure
69
+ // ---------------------------------------------------------------------------
70
+ describe("DecaySearchPage — structure", () => {
71
+ beforeEach(() => {
72
+ mockRows = [];
73
+ });
74
+ it("renders the 'Decay search' heading", async () => {
75
+ await renderPageReady();
76
+ expect(screen.getByText(/decay search/i)).toBeInTheDocument();
77
+ });
78
+ it("renders the guide link button", async () => {
79
+ await renderPageReady();
80
+ expect(screen.getByTestId("guide-link")).toBeInTheDocument();
81
+ });
82
+ it("renders particle dropdown controls", async () => {
83
+ await renderPageReady();
84
+ expect(screen.getAllByTestId("particle-dropdown").length).toBeGreaterThan(0);
85
+ });
86
+ it("renders tag dropdown controls", async () => {
87
+ await renderPageReady();
88
+ expect(screen.getAllByTestId("tag-dropdown").length).toBeGreaterThan(0);
89
+ });
90
+ it("renders the 'Show only selected' checkbox", async () => {
91
+ await renderPageReady();
92
+ expect(screen.getByText(/show only selected/i)).toBeInTheDocument();
93
+ });
94
+ });
95
+ // ---------------------------------------------------------------------------
96
+ // Tests — decay list
97
+ // ---------------------------------------------------------------------------
98
+ describe("DecaySearchPage — decay list", () => {
99
+ beforeEach(() => {
100
+ mockRows = [];
101
+ });
102
+ it("renders the decay list after tags load", async () => {
103
+ await renderPageReady();
104
+ expect(screen.getByTestId("decay-list")).toBeInTheDocument();
105
+ });
106
+ it("shows the decay from mockMetadata in the list", async () => {
107
+ await renderPageReady();
108
+ expect(screen.getByText("[B+ -> K+ mu+ mu-]cc")).toBeInTheDocument();
109
+ });
110
+ });
111
+ // ---------------------------------------------------------------------------
112
+ // Tests — Select button
113
+ // ---------------------------------------------------------------------------
114
+ describe("DecaySearchPage — Select button", () => {
115
+ beforeEach(() => {
116
+ mockRows = [];
117
+ });
118
+ it("renders the Select button", async () => {
119
+ await renderPageReady();
120
+ expect(screen.getByRole("button", { name: /select/i })).toBeInTheDocument();
121
+ });
122
+ it("shows 0 selected decays initially", async () => {
123
+ await renderPageReady();
124
+ // The badge inside the button shows the count
125
+ expect(screen.getByText("0")).toBeInTheDocument();
126
+ });
127
+ it("increments the selected count when a decay is clicked", async () => {
128
+ await renderPageReady();
129
+ fireEvent.click(screen.getByTestId("decay-list-item"));
130
+ await waitFor(() => expect(screen.getByText("1")).toBeInTheDocument());
131
+ });
132
+ it("pre-populates selectedDecays from existing rows", async () => {
133
+ mockRows = [createMockRow({ id: 0, decay: mockDecay })];
134
+ await renderPageReady();
135
+ // The count badge should show 1 because the row's decay is pre-selected
136
+ expect(screen.getByText("1")).toBeInTheDocument();
137
+ });
138
+ });
139
+ // ---------------------------------------------------------------------------
140
+ // Tests — sendData / setRows
141
+ // ---------------------------------------------------------------------------
142
+ describe("DecaySearchPage — sending data", () => {
143
+ beforeEach(() => {
144
+ mockRows = [];
145
+ mockSetRows.mockClear();
146
+ });
147
+ it("calls setRows when the Select button is clicked", async () => {
148
+ await renderPageReady();
149
+ fireEvent.click(screen.getByRole("button", { name: /select/i }));
150
+ expect(mockSetRows).toHaveBeenCalledOnce();
151
+ });
152
+ it("passes selected decays to setRows", async () => {
153
+ await renderPageReady();
154
+ // Select a decay from the list
155
+ fireEvent.click(screen.getByTestId("decay-list-item"));
156
+ // Click the Select button
157
+ fireEvent.click(screen.getByRole("button", { name: /select/i }));
158
+ const calledWith = mockSetRows.mock.calls[0][0];
159
+ expect(calledWith).toHaveLength(1);
160
+ expect(calledWith[0].decay.descriptors.plain).toBe("[B+ -> K+ mu+ mu-]cc");
161
+ });
162
+ it("preserves existing row config (dtt, line, paths) for re-selected decays", async () => {
163
+ const existingRow = createMockRow({
164
+ id: 0,
165
+ decay: mockDecay,
166
+ paths: ["/some/path/DIMUON.DST"],
167
+ });
168
+ mockRows = [existingRow];
169
+ await renderPageReady();
170
+ fireEvent.click(screen.getByRole("button", { name: /select/i }));
171
+ const calledWith = mockSetRows.mock.calls[0][0];
172
+ // The existing row should be preserved (same paths)
173
+ expect(calledWith[0].paths).toEqual(["/some/path/DIMUON.DST"]);
174
+ });
175
+ it("removes a row when its decay is deselected before clicking Select", async () => {
176
+ // Render with an existing row so the decay starts pre-selected
177
+ mockRows = [createMockRow({ id: 0, decay: mockDecay })];
178
+ await renderPageReady();
179
+ // Click the decay list item to deselect it (mock toggles selection)
180
+ const listItem = screen.getByTestId("decay-list-item");
181
+ expect(listItem).toHaveAttribute("data-selected", "true");
182
+ fireEvent.click(listItem);
183
+ await waitFor(() => expect(screen.getByText("0")).toBeInTheDocument());
184
+ // Click Select — the deselected decay's row should not be included
185
+ fireEvent.click(screen.getByRole("button", { name: /select/i }));
186
+ const calledWith = mockSetRows.mock.calls[0][0];
187
+ expect(calledWith).toHaveLength(0);
188
+ });
189
+ });
190
+ // ---------------------------------------------------------------------------
191
+ // Tests — filter controls behaviour
192
+ // ---------------------------------------------------------------------------
193
+ describe("DecaySearchPage — filter controls", () => {
194
+ beforeEach(() => {
195
+ mockRows = [];
196
+ });
197
+ it("renders the 'Head' dropdown button", async () => {
198
+ await renderPageReady();
199
+ expect(screen.getByRole("button", { name: /head/i })).toBeInTheDocument();
200
+ });
201
+ it("renders the 'Contains' dropdown button", async () => {
202
+ await renderPageReady();
203
+ expect(screen.getByRole("button", { name: /contains/i })).toBeInTheDocument();
204
+ });
205
+ it("renders the 'Tags' dropdown button", async () => {
206
+ await renderPageReady();
207
+ expect(screen.getByRole("button", { name: /tags/i })).toBeInTheDocument();
208
+ });
209
+ it("shows a ParticleDropdown for head with placeholder when headMatchType=exactly (default)", async () => {
210
+ await renderPageReady();
211
+ // Two ParticleDropdowns exist (head + contains); find the head one by placeholder
212
+ const headDropdown = screen.getByPlaceholderText("DecayLatex head");
213
+ expect(headDropdown).toBeInTheDocument();
214
+ });
215
+ it("switches to a TagDropdown for head when headMatchType is changed to 'category'", async () => {
216
+ await renderPageReady();
217
+ // Click the Head dropdown toggle to open it
218
+ const headBtn = screen.getByRole("button", { name: /head/i });
219
+ fireEvent.click(headBtn);
220
+ // Click the "category" dropdown item
221
+ const categoryItem = screen.getByText("category");
222
+ fireEvent.click(categoryItem);
223
+ // Now TagDropdown should replace ParticleDropdown for the head filter
224
+ const tagDropdowns = screen.getAllByTestId("tag-dropdown");
225
+ const headTagDropdown = tagDropdowns.find((el) => el.getAttribute("placeholder") === "DecayLatex head");
226
+ expect(headTagDropdown).toBeInTheDocument();
227
+ });
228
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,105 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { render, screen, fireEvent, waitFor } from "@testing-library/react";
4
+ import { DecayTreeConfigPage } from "../../pages/DecayTreeConfigPage";
5
+ import { MemoryRouter } from "react-router-dom";
6
+ import { createMockDtt, createMockRow, mockDecay } from "../testUtils";
7
+ // ---------------------------------------------------------------------------
8
+ // Provider mocks
9
+ // ---------------------------------------------------------------------------
10
+ const mockNavigate = vi.fn();
11
+ vi.mock("react-router-dom", async (importOriginal) => {
12
+ const actual = await importOriginal();
13
+ return { ...actual, useNavigate: () => mockNavigate };
14
+ });
15
+ let mockRows = [];
16
+ vi.mock("../../providers/RowsProvider", () => ({
17
+ useRows: () => ({
18
+ rows: mockRows,
19
+ configuredRows: mockRows.filter((r) => r.dtt),
20
+ setRows: vi.fn(),
21
+ updateRow: vi.fn(),
22
+ removeRow: vi.fn(),
23
+ generateAllFiles: vi.fn(),
24
+ }),
25
+ }));
26
+ vi.mock("../../providers/WizardConfigProvider", () => ({
27
+ useWizardConfig: () => ({ variant: "standalone", basePath: "" }),
28
+ }));
29
+ // ---------------------------------------------------------------------------
30
+ // Child component mocks
31
+ // ---------------------------------------------------------------------------
32
+ // DecayTreeCard uses Cytoscape which cannot run in jsdom; replace with a stub
33
+ vi.mock("../../components/DecayTreeCard", () => ({
34
+ DecayTreeCard: () => _jsx("div", { "data-testid": "decay-tree-card" }),
35
+ }));
36
+ vi.mock("../../providers/DttProvider", () => ({ DttProvider: ({ children }) => children }));
37
+ vi.mock("../../providers/RowProvider", () => ({ RowProvider: ({ children }) => children }));
38
+ // ---------------------------------------------------------------------------
39
+ // Helpers
40
+ // ---------------------------------------------------------------------------
41
+ function renderPage() {
42
+ return render(_jsx(MemoryRouter, { children: _jsx(DecayTreeConfigPage, {}) }));
43
+ }
44
+ function createRowWithDtt(id, editTree = false) {
45
+ return createMockRow({
46
+ id,
47
+ decay: mockDecay,
48
+ dtt: createMockDtt(`Tree${id}`),
49
+ editTree,
50
+ });
51
+ }
52
+ // ---------------------------------------------------------------------------
53
+ // Tests — structure
54
+ // ---------------------------------------------------------------------------
55
+ describe("DecayTreeConfigPage — structure", () => {
56
+ beforeEach(() => {
57
+ mockRows = [];
58
+ });
59
+ it("renders the 'DecayTreeTuple configuration' heading", () => {
60
+ renderPage();
61
+ expect(screen.getByText(/decaytreetuple configuration/i)).toBeInTheDocument();
62
+ });
63
+ it("renders the Return button", () => {
64
+ renderPage();
65
+ expect(screen.getByRole("button", { name: /return/i })).toBeInTheDocument();
66
+ });
67
+ });
68
+ // ---------------------------------------------------------------------------
69
+ // Tests — conditional rendering based on editTree flag
70
+ // ---------------------------------------------------------------------------
71
+ describe("DecayTreeConfigPage — editTree filtering", () => {
72
+ it("shows no DecayTreeCard when no rows have editTree=true", () => {
73
+ mockRows = [createRowWithDtt(0, false), createRowWithDtt(1, false)];
74
+ renderPage();
75
+ expect(screen.queryByTestId("decay-tree-card")).not.toBeInTheDocument();
76
+ });
77
+ it("shows a DecayTreeCard for each row with editTree=true", () => {
78
+ mockRows = [createRowWithDtt(0, true), createRowWithDtt(1, true)];
79
+ renderPage();
80
+ expect(screen.getAllByTestId("decay-tree-card")).toHaveLength(2);
81
+ });
82
+ it("shows only the rows with editTree=true, not others", () => {
83
+ mockRows = [createRowWithDtt(0, true), createRowWithDtt(1, false), createRowWithDtt(2, true)];
84
+ renderPage();
85
+ expect(screen.getAllByTestId("decay-tree-card")).toHaveLength(2);
86
+ });
87
+ it("shows no cards when rows list is empty", () => {
88
+ mockRows = [];
89
+ renderPage();
90
+ expect(screen.queryByTestId("decay-tree-card")).not.toBeInTheDocument();
91
+ });
92
+ });
93
+ // ---------------------------------------------------------------------------
94
+ // Tests — navigation
95
+ // ---------------------------------------------------------------------------
96
+ describe("DecayTreeConfigPage — Return button navigation", () => {
97
+ beforeEach(() => {
98
+ mockRows = [];
99
+ });
100
+ it("navigates to basePath when Return is clicked", async () => {
101
+ renderPage();
102
+ fireEvent.click(screen.getByRole("button", { name: /return/i }));
103
+ await waitFor(() => expect(mockNavigate).toHaveBeenCalledWith(""));
104
+ });
105
+ });
@@ -0,0 +1 @@
1
+ export {};