@pie-lib/graphing-solution-set 3.1.1-next.0 → 3.2.0-next.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 (124) hide show
  1. package/lib/axis/arrow.js +0 -3
  2. package/lib/axis/arrow.js.map +1 -1
  3. package/lib/axis/axes.js +0 -16
  4. package/lib/axis/axes.js.map +1 -1
  5. package/lib/axis/index.js +0 -7
  6. package/lib/axis/index.js.map +1 -1
  7. package/lib/bg.js +0 -6
  8. package/lib/bg.js.map +1 -1
  9. package/lib/container/actions.js +0 -1
  10. package/lib/container/actions.js.map +1 -1
  11. package/lib/container/index.js +4 -10
  12. package/lib/container/index.js.map +1 -1
  13. package/lib/container/marks.js +0 -2
  14. package/lib/container/marks.js.map +1 -1
  15. package/lib/container/middleware.js +0 -1
  16. package/lib/container/middleware.js.map +1 -1
  17. package/lib/container/reducer.js +0 -1
  18. package/lib/container/reducer.js.map +1 -1
  19. package/lib/coordinates-label.js +0 -11
  20. package/lib/coordinates-label.js.map +1 -1
  21. package/lib/graph-with-controls.js +3 -22
  22. package/lib/graph-with-controls.js.map +1 -1
  23. package/lib/graph.js +7 -26
  24. package/lib/graph.js.map +1 -1
  25. package/lib/grid-setup.js +0 -11
  26. package/lib/grid-setup.js.map +1 -1
  27. package/lib/grid.js +0 -22
  28. package/lib/grid.js.map +1 -1
  29. package/lib/index.js +0 -7
  30. package/lib/index.js.map +1 -1
  31. package/lib/labels.js +0 -13
  32. package/lib/labels.js.map +1 -1
  33. package/lib/mark-label.js +0 -16
  34. package/lib/mark-label.js.map +1 -1
  35. package/lib/toggle-bar.js +0 -17
  36. package/lib/toggle-bar.js.map +1 -1
  37. package/lib/tool-menu.js +0 -3
  38. package/lib/tool-menu.js.map +1 -1
  39. package/lib/tools/index.js +0 -1
  40. package/lib/tools/index.js.map +1 -1
  41. package/lib/tools/line/component.js +0 -13
  42. package/lib/tools/line/component.js.map +1 -1
  43. package/lib/tools/line/index.js +0 -1
  44. package/lib/tools/line/index.js.map +1 -1
  45. package/lib/tools/polygon/component.js +5 -25
  46. package/lib/tools/polygon/component.js.map +1 -1
  47. package/lib/tools/polygon/index.js +0 -12
  48. package/lib/tools/polygon/index.js.map +1 -1
  49. package/lib/tools/polygon/line.js +0 -16
  50. package/lib/tools/polygon/line.js.map +1 -1
  51. package/lib/tools/polygon/polygon.js +0 -19
  52. package/lib/tools/polygon/polygon.js.map +1 -1
  53. package/lib/tools/shared/arrow-head.js +0 -3
  54. package/lib/tools/shared/arrow-head.js.map +1 -1
  55. package/lib/tools/shared/line/index.js +7 -22
  56. package/lib/tools/shared/line/index.js.map +1 -1
  57. package/lib/tools/shared/line/line-path.js +0 -16
  58. package/lib/tools/shared/line/line-path.js.map +1 -1
  59. package/lib/tools/shared/line/with-root-edge.js +0 -11
  60. package/lib/tools/shared/line/with-root-edge.js.map +1 -1
  61. package/lib/tools/shared/point/arrow-point.js +2 -5
  62. package/lib/tools/shared/point/arrow-point.js.map +1 -1
  63. package/lib/tools/shared/point/arrow.js +0 -3
  64. package/lib/tools/shared/point/arrow.js.map +1 -1
  65. package/lib/tools/shared/point/base-point.js +0 -11
  66. package/lib/tools/shared/point/base-point.js.map +1 -1
  67. package/lib/tools/shared/point/index.js +0 -16
  68. package/lib/tools/shared/point/index.js.map +1 -1
  69. package/lib/tools/shared/styles.js +0 -1
  70. package/lib/tools/shared/styles.js.map +1 -1
  71. package/lib/tools/shared/types.js +0 -1
  72. package/lib/tools/shared/types.js.map +1 -1
  73. package/lib/undo-redo.js +0 -2
  74. package/lib/undo-redo.js.map +1 -1
  75. package/lib/use-debounce.js +0 -2
  76. package/lib/use-debounce.js.map +1 -1
  77. package/lib/utils.js +8 -26
  78. package/lib/utils.js.map +1 -1
  79. package/package.json +14 -11
  80. package/src/__tests__/bg.test.jsx +250 -0
  81. package/src/__tests__/coordinates-label.test.jsx +243 -0
  82. package/src/__tests__/graph-with-controls.test.jsx +9 -10
  83. package/src/__tests__/graph.test.jsx +0 -2
  84. package/src/__tests__/grid-setup.test.jsx +645 -0
  85. package/src/__tests__/mark-label.test.jsx +1 -1
  86. package/src/__tests__/tool-menu.test.jsx +422 -2
  87. package/src/__tests__/use-debounce.test.js +1 -1
  88. package/src/__tests__/utils.test.js +15 -61
  89. package/src/axis/__tests__/axes.test.jsx +1 -1
  90. package/src/axis/axes.jsx +7 -21
  91. package/src/axis/index.js +1 -0
  92. package/src/bg.jsx +1 -1
  93. package/src/container/__tests__/actions.test.js +105 -0
  94. package/src/container/__tests__/index.test.jsx +227 -0
  95. package/src/container/__tests__/marks.test.js +172 -0
  96. package/src/container/__tests__/middleware.test.js +235 -0
  97. package/src/container/__tests__/reducer.test.js +324 -0
  98. package/src/container/index.jsx +3 -4
  99. package/src/coordinates-label.jsx +1 -7
  100. package/src/graph-with-controls.jsx +7 -25
  101. package/src/graph.jsx +3 -4
  102. package/src/grid-setup.jsx +1 -1
  103. package/src/mark-label.jsx +2 -2
  104. package/src/toggle-bar.jsx +8 -1
  105. package/src/tool-menu.jsx +1 -1
  106. package/src/tools/line/__tests__/component.test.jsx +1 -0
  107. package/src/tools/line/component.jsx +2 -2
  108. package/src/tools/polygon/__tests__/component.test.jsx +417 -5
  109. package/src/tools/polygon/__tests__/polygon.test.jsx +1 -1
  110. package/src/tools/polygon/component.jsx +4 -14
  111. package/src/tools/polygon/line.jsx +1 -1
  112. package/src/tools/shared/line/__tests__/index.test.jsx +460 -17
  113. package/src/tools/shared/line/__tests__/line-path.test.jsx +7 -4
  114. package/src/tools/shared/line/__tests__/with-root-edge.test.jsx +439 -14
  115. package/src/tools/shared/line/index.jsx +4 -6
  116. package/src/tools/shared/line/line-path.jsx +2 -8
  117. package/src/tools/shared/point/__tests__/arrow.test.jsx +469 -0
  118. package/src/tools/shared/point/arrow-point.jsx +2 -2
  119. package/src/tools/shared/point/base-point.jsx +1 -1
  120. package/src/tools/shared/point/index.jsx +1 -1
  121. package/src/undo-redo.jsx +1 -3
  122. package/src/use-debounce.js +1 -1
  123. package/src/utils.js +1 -5
  124. package/NEXT.CHANGELOG.json +0 -16
@@ -1,4 +1,4 @@
1
- import { lineTool, lineToolComponent, lineBase } from '../index';
1
+ import { lineBase, lineTool, lineToolComponent } from '../index';
2
2
  import { utils } from '@pie-lib/plot';
3
3
  import { render } from '@pie-lib/test-utils';
4
4
  import React from 'react';
@@ -7,14 +7,15 @@ import { graphProps as getGraphProps } from '../../../../__tests__/utils';
7
7
  const { xy } = utils;
8
8
  const xyLabel = (x, y, label) => ({ x, y, label });
9
9
 
10
- // Pure function tests - keep as-is
11
10
  describe('lineTool', () => {
12
11
  describe('addPoint', () => {
13
12
  let toolbar;
13
+
14
14
  beforeEach(() => {
15
15
  toolbar = lineTool('lineType', () => <div />)();
16
16
  });
17
- it('returns a building mark', () => {
17
+
18
+ it('returns a building mark when no existing mark', () => {
18
19
  const result = toolbar.addPoint(xy(1, 1));
19
20
  expect(result).toEqual({
20
21
  type: 'lineType',
@@ -23,7 +24,7 @@ describe('lineTool', () => {
23
24
  });
24
25
  });
25
26
 
26
- it('returns a complete mark', () => {
27
+ it('returns a complete mark when adding second point', () => {
27
28
  const result = toolbar.addPoint(xy(1, 1), { from: xy(0, 0) });
28
29
  expect(result).toEqual({
29
30
  building: false,
@@ -31,24 +32,68 @@ describe('lineTool', () => {
31
32
  to: xy(1, 1),
32
33
  });
33
34
  });
35
+
36
+ it('returns same mark if point equals existing from point', () => {
37
+ const existingMark = { from: xy(1, 1), building: true };
38
+ const result = toolbar.addPoint(xy(1, 1), existingMark);
39
+ expect(result).toEqual(existingMark);
40
+ });
41
+
42
+ it('handles adding point with root property', () => {
43
+ const existingMark = { root: xy(1, 1), building: true };
44
+ const result = toolbar.addPoint(xy(1, 1), existingMark);
45
+ expect(result).toEqual(existingMark);
46
+ });
47
+
48
+ it('creates different types correctly', () => {
49
+ const lineA = lineTool('lineA', () => <div />)();
50
+ const lineB = lineTool('lineB', () => <div />)();
51
+
52
+ const resultA = lineA.addPoint(xy(1, 1));
53
+ const resultB = lineB.addPoint(xy(1, 1));
54
+
55
+ expect(resultA.type).toBe('lineA');
56
+ expect(resultB.type).toBe('lineB');
57
+ });
58
+
59
+ it('preserves building state correctly', () => {
60
+ const building = toolbar.addPoint(xy(1, 1));
61
+ expect(building.building).toBe(true);
62
+
63
+ const complete = toolbar.addPoint(xy(2, 2), building);
64
+ expect(complete.building).toBe(false);
65
+ });
66
+ });
67
+
68
+ describe('Component property', () => {
69
+ it('stores the provided Component', () => {
70
+ const TestComp = () => <div>Test</div>;
71
+ const tool = lineTool('test', TestComp)();
72
+ expect(tool.Component).toBe(TestComp);
73
+ });
74
+
75
+ it('stores the correct type', () => {
76
+ const tool = lineTool('customType', () => <div />)();
77
+ expect(tool.type).toBe('customType');
78
+ });
34
79
  });
35
80
  });
36
81
 
37
- // Note: Instance method tests have been removed. Component behavior should be tested
38
- // through user interactions and integration tests.
39
82
  describe('lineToolComponent', () => {
40
83
  let Comp;
41
84
  let mark;
85
+ let onChange;
42
86
 
43
87
  beforeEach(() => {
44
- Comp = lineToolComponent(() => <text />);
45
- mark = { from: xy(0, 0), to: xy(1, 1) };
88
+ onChange = jest.fn();
89
+ Comp = lineToolComponent(() => <text data-testid="line-component" />);
90
+ mark = { from: xy(0, 0), to: xy(1, 1), type: 'line' };
46
91
  });
47
92
 
48
93
  const renderComponent = (extras) => {
49
94
  const defaults = {
50
95
  mark,
51
- onChange: jest.fn(),
96
+ onChange,
52
97
  graphProps: getGraphProps(),
53
98
  };
54
99
  const props = { ...defaults, ...extras };
@@ -56,28 +101,170 @@ describe('lineToolComponent', () => {
56
101
  };
57
102
 
58
103
  describe('rendering', () => {
59
- it('renders', () => {
104
+ it('renders without crashing', () => {
60
105
  const { container } = renderComponent();
61
106
  expect(container.firstChild).toBeInTheDocument();
62
107
  });
108
+
109
+ it('renders with building mark', () => {
110
+ const buildingMark = { from: xy(0, 0), building: true, type: 'line' };
111
+ const { container } = renderComponent({ mark: buildingMark });
112
+ expect(container.firstChild).toBeInTheDocument();
113
+ });
114
+
115
+ it('renders with background mark', () => {
116
+ const bgMark = { from: xy(0, 0), to: xy(1, 1), isBackground: true, type: 'line' };
117
+ const { container } = renderComponent({ mark: bgMark });
118
+ expect(container.firstChild).toBeInTheDocument();
119
+ });
120
+
121
+ it('renders with disabled mark', () => {
122
+ const disabledMark = { from: xy(0, 0), to: xy(1, 1), disabled: true, type: 'line' };
123
+ const { container } = renderComponent({ mark: disabledMark });
124
+ expect(container.firstChild).toBeInTheDocument();
125
+ });
126
+
127
+ it('renders with correctness states', () => {
128
+ const correctMark = { from: xy(0, 0), to: xy(1, 1), correctness: 'correct', type: 'line' };
129
+ const { container } = renderComponent({ mark: correctMark });
130
+ expect(container.firstChild).toBeInTheDocument();
131
+ });
132
+
133
+ it('renders with middle point', () => {
134
+ const markWithMiddle = { from: xy(0, 0), to: xy(1, 1), middle: xy(0.5, 0.5), type: 'line' };
135
+ const { container } = renderComponent({ mark: markWithMiddle });
136
+ expect(container.firstChild).toBeInTheDocument();
137
+ });
138
+
139
+ it('renders with fill color', () => {
140
+ const coloredMark = { from: xy(0, 0), to: xy(1, 1), fill: '#ff0000', type: 'line' };
141
+ const { container } = renderComponent({ mark: coloredMark });
142
+ expect(container.firstChild).toBeInTheDocument();
143
+ });
144
+
145
+ it('renders with gssLineData', () => {
146
+ const gssLineData = { selectedTool: 'lineA' };
147
+ const { container } = renderComponent({ gssLineData });
148
+ expect(container.firstChild).toBeInTheDocument();
149
+ });
150
+
151
+ it('renders with labelNode', () => {
152
+ const labelNode = document.createElement('foreignObject');
153
+ const { container } = renderComponent({ labelNode });
154
+ expect(container.firstChild).toBeInTheDocument();
155
+ });
156
+
157
+ it('renders with coordinatesOnHover enabled', () => {
158
+ const { container } = renderComponent({ coordinatesOnHover: true });
159
+ expect(container.firstChild).toBeInTheDocument();
160
+ });
161
+
162
+ it('renders with labelModeEnabled', () => {
163
+ const { container } = renderComponent({ labelModeEnabled: true });
164
+ expect(container.firstChild).toBeInTheDocument();
165
+ });
166
+ });
167
+
168
+ describe('state management', () => {
169
+ it('initializes with empty state', () => {
170
+ const { container } = renderComponent();
171
+ expect(container.firstChild).toBeInTheDocument();
172
+ // State should be empty initially
173
+ });
174
+
175
+ it('handles mark updates through props', () => {
176
+ const { rerender, container } = renderComponent();
177
+ const updatedMark = { from: xy(1, 1), to: xy(2, 2), type: 'line' };
178
+
179
+ rerender(<Comp mark={updatedMark} onChange={onChange} graphProps={getGraphProps()} />);
180
+ expect(container.firstChild).toBeInTheDocument();
181
+ });
182
+ });
183
+
184
+ describe('background mark handling', () => {
185
+ it('disables from point when mark is background', () => {
186
+ const bgMark = {
187
+ from: xy(0, 0),
188
+ to: xy(1, 1),
189
+ isBackground: true,
190
+ type: 'line',
191
+ };
192
+ const { container } = renderComponent({ mark: bgMark });
193
+ expect(container.firstChild).toBeInTheDocument();
194
+ // from.disabled should be true
195
+ });
196
+
197
+ it('disables to point when mark is background', () => {
198
+ const bgMark = {
199
+ from: xy(0, 0),
200
+ to: xy(1, 1),
201
+ isBackground: true,
202
+ type: 'line',
203
+ };
204
+ const { container } = renderComponent({ mark: bgMark });
205
+ expect(container.firstChild).toBeInTheDocument();
206
+ // to.disabled should be true
207
+ });
208
+
209
+ it('disables middle point when mark is background', () => {
210
+ const bgMark = {
211
+ from: xy(0, 0),
212
+ to: xy(1, 1),
213
+ middle: xy(0.5, 0.5),
214
+ isBackground: true,
215
+ type: 'line',
216
+ };
217
+ const { container } = renderComponent({ mark: bgMark });
218
+ expect(container.firstChild).toBeInTheDocument();
219
+ // middle.disabled should be true
220
+ });
221
+ });
222
+
223
+ describe('edge cases', () => {
224
+ it('handles mark without to point', () => {
225
+ const incompleteMark = { from: xy(0, 0), type: 'line' };
226
+ const { container } = renderComponent({ mark: incompleteMark });
227
+ expect(container.firstChild).toBeInTheDocument();
228
+ });
229
+
230
+ it('handles mark with only from point', () => {
231
+ const singlePointMark = { from: xy(0, 0), building: true, type: 'line' };
232
+ const { container } = renderComponent({ mark: singlePointMark });
233
+ expect(container.firstChild).toBeInTheDocument();
234
+ });
235
+
236
+ it('handles different line types', () => {
237
+ const parabola = { from: xy(0, 0), to: xy(1, 1), type: 'parabola' };
238
+ const sine = { from: xy(0, 0), to: xy(1, 1), type: 'sine' };
239
+ const absolute = { from: xy(0, 0), to: xy(1, 1), type: 'absolute' };
240
+ const exponential = { from: xy(0, 0), to: xy(1, 1), type: 'exponential' };
241
+
242
+ render(<Comp mark={parabola} onChange={onChange} graphProps={getGraphProps()} />);
243
+ render(<Comp mark={sine} onChange={onChange} graphProps={getGraphProps()} />);
244
+ render(<Comp mark={absolute} onChange={onChange} graphProps={getGraphProps()} />);
245
+ render(<Comp mark={exponential} onChange={onChange} graphProps={getGraphProps()} />);
246
+ });
63
247
  });
64
248
  });
65
249
 
66
- // Note: Instance method tests have been removed. Component behavior should be tested
67
- // through user interactions and integration tests.
68
250
  describe('lineBase', () => {
69
251
  let Comp;
70
- let onChange = jest.fn();
71
- let changeMarkProps = jest.fn();
252
+ let onChange;
253
+ let changeMarkProps;
254
+ let onClick;
72
255
 
73
256
  beforeEach(() => {
74
- Comp = lineBase(() => <text />);
257
+ onChange = jest.fn();
258
+ changeMarkProps = jest.fn();
259
+ onClick = jest.fn();
260
+ Comp = lineBase(() => <text data-testid="line-base" />);
75
261
  });
76
262
 
77
263
  const renderComponent = (extras) => {
78
264
  const defaults = {
79
265
  onChange,
80
266
  changeMarkProps,
267
+ onClick,
81
268
  graphProps: getGraphProps(),
82
269
  from: xy(0, 0),
83
270
  to: xy(1, 1),
@@ -86,7 +273,6 @@ describe('lineBase', () => {
86
273
  return render(<Comp {...props} />);
87
274
  };
88
275
 
89
- // used to test items that have labels attached to points
90
276
  const labelNode = document.createElement('foreignObject');
91
277
  const renderWithLabels = (extras = {}) =>
92
278
  renderComponent({
@@ -97,7 +283,7 @@ describe('lineBase', () => {
97
283
  });
98
284
 
99
285
  describe('rendering', () => {
100
- it('renders', () => {
286
+ it('renders without crashing', () => {
101
287
  const { container } = renderComponent();
102
288
  expect(container.firstChild).toBeInTheDocument();
103
289
  });
@@ -106,5 +292,262 @@ describe('lineBase', () => {
106
292
  const { container } = renderWithLabels();
107
293
  expect(container.firstChild).toBeInTheDocument();
108
294
  });
295
+
296
+ it('renders with middle point label', () => {
297
+ const { container } = renderComponent({
298
+ labelNode,
299
+ middle: xyLabel(0.5, 0.5, 'M'),
300
+ });
301
+ expect(container.firstChild).toBeInTheDocument();
302
+ });
303
+
304
+ it('renders with only from label', () => {
305
+ const { container } = renderComponent({
306
+ labelNode,
307
+ from: xyLabel(0, 0, 'Start'),
308
+ to: xy(1, 1),
309
+ });
310
+ expect(container.firstChild).toBeInTheDocument();
311
+ });
312
+
313
+ it('renders with only to label', () => {
314
+ const { container } = renderComponent({
315
+ labelNode,
316
+ from: xy(0, 0),
317
+ to: xyLabel(1, 1, 'End'),
318
+ });
319
+ expect(container.firstChild).toBeInTheDocument();
320
+ });
321
+
322
+ it('renders with all three labels', () => {
323
+ const { container } = renderComponent({
324
+ labelNode,
325
+ from: xyLabel(0, 0, 'A'),
326
+ to: xyLabel(1, 1, 'B'),
327
+ middle: xyLabel(0.5, 0.5, 'M'),
328
+ });
329
+ expect(container.firstChild).toBeInTheDocument();
330
+ });
331
+ });
332
+
333
+ describe('gssLineData handling', () => {
334
+ it('renders normally without gssLineData', () => {
335
+ const { container } = renderComponent();
336
+ expect(container.firstChild).toBeInTheDocument();
337
+ });
338
+
339
+ it('renders with gssLineData when solutionSet is selected', () => {
340
+ const gssLineData = { selectedTool: 'solutionSet' };
341
+ const { container } = renderComponent({ gssLineData });
342
+ expect(container.firstChild).toBeInTheDocument();
343
+ });
344
+
345
+ it('renders with gssLineData when lineA is selected', () => {
346
+ const gssLineData = { selectedTool: 'lineA' };
347
+ const { container } = renderComponent({ gssLineData });
348
+ expect(container.firstChild).toBeInTheDocument();
349
+ });
350
+
351
+ it('renders with gssLineData when lineB is selected', () => {
352
+ const gssLineData = { selectedTool: 'lineB' };
353
+ const { container } = renderComponent({ gssLineData });
354
+ expect(container.firstChild).toBeInTheDocument();
355
+ });
356
+ });
357
+
358
+ describe('disabled state', () => {
359
+ it('renders when disabled', () => {
360
+ const { container } = renderComponent({ disabled: true });
361
+ expect(container.firstChild).toBeInTheDocument();
362
+ });
363
+
364
+ it('renders when not disabled', () => {
365
+ const { container } = renderComponent({ disabled: false });
366
+ expect(container.firstChild).toBeInTheDocument();
367
+ });
368
+ });
369
+
370
+ describe('correctness states', () => {
371
+ it('renders with correct state', () => {
372
+ const { container } = renderComponent({ correctness: 'correct' });
373
+ expect(container.firstChild).toBeInTheDocument();
374
+ });
375
+
376
+ it('renders with incorrect state', () => {
377
+ const { container } = renderComponent({ correctness: 'incorrect' });
378
+ expect(container.firstChild).toBeInTheDocument();
379
+ });
380
+
381
+ it('renders with missing state', () => {
382
+ const { container } = renderComponent({ correctness: 'missing' });
383
+ expect(container.firstChild).toBeInTheDocument();
384
+ });
385
+
386
+ it('renders without correctness', () => {
387
+ const { container } = renderComponent({ correctness: undefined });
388
+ expect(container.firstChild).toBeInTheDocument();
389
+ });
390
+ });
391
+
392
+ describe('fill color', () => {
393
+ it('renders with custom fill color', () => {
394
+ const { container } = renderComponent({ fill: '#ff0000' });
395
+ expect(container.firstChild).toBeInTheDocument();
396
+ });
397
+
398
+ it('renders without fill color', () => {
399
+ const { container } = renderComponent({ fill: undefined });
400
+ expect(container.firstChild).toBeInTheDocument();
401
+ });
402
+ });
403
+
404
+ describe('coordinates on hover', () => {
405
+ it('renders with coordinatesOnHover enabled', () => {
406
+ const { container } = renderComponent({ coordinatesOnHover: true });
407
+ expect(container.firstChild).toBeInTheDocument();
408
+ });
409
+
410
+ it('renders with coordinatesOnHover disabled', () => {
411
+ const { container } = renderComponent({ coordinatesOnHover: false });
412
+ expect(container.firstChild).toBeInTheDocument();
413
+ });
414
+ });
415
+
416
+ describe('label mode', () => {
417
+ it('renders with labelModeEnabled', () => {
418
+ const { container } = renderComponent({
419
+ labelModeEnabled: true,
420
+ labelNode,
421
+ });
422
+ expect(container.firstChild).toBeInTheDocument();
423
+ });
424
+
425
+ it('renders without labelModeEnabled', () => {
426
+ const { container } = renderComponent({
427
+ labelModeEnabled: false,
428
+ labelNode,
429
+ });
430
+ expect(container.firstChild).toBeInTheDocument();
431
+ });
432
+ });
433
+
434
+ describe('drag callbacks', () => {
435
+ it('renders with onDragStart callback', () => {
436
+ const onDragStart = jest.fn();
437
+ const { container } = renderComponent({ onDragStart });
438
+ expect(container.firstChild).toBeInTheDocument();
439
+ });
440
+
441
+ it('renders with onDragStop callback', () => {
442
+ const onDragStop = jest.fn();
443
+ const { container } = renderComponent({ onDragStop });
444
+ expect(container.firstChild).toBeInTheDocument();
445
+ });
446
+
447
+ it('renders with both drag callbacks', () => {
448
+ const onDragStart = jest.fn();
449
+ const onDragStop = jest.fn();
450
+ const { container } = renderComponent({ onDragStart, onDragStop });
451
+ expect(container.firstChild).toBeInTheDocument();
452
+ });
453
+ });
454
+
455
+ describe('edge cases', () => {
456
+ it('handles equal from and to points', () => {
457
+ const { container } = renderComponent({
458
+ from: xy(1, 1),
459
+ to: xy(1, 1),
460
+ });
461
+ expect(container.firstChild).toBeInTheDocument();
462
+ });
463
+
464
+ it('handles negative coordinates', () => {
465
+ const { container } = renderComponent({
466
+ from: xy(-5, -5),
467
+ to: xy(-1, -1),
468
+ });
469
+ expect(container.firstChild).toBeInTheDocument();
470
+ });
471
+
472
+ it('handles large coordinate values', () => {
473
+ const { container } = renderComponent({
474
+ from: xy(100, 100),
475
+ to: xy(200, 200),
476
+ });
477
+ expect(container.firstChild).toBeInTheDocument();
478
+ });
479
+
480
+ it('handles decimal coordinates', () => {
481
+ const { container } = renderComponent({
482
+ from: xy(0.5, 0.5),
483
+ to: xy(1.5, 1.5),
484
+ });
485
+ expect(container.firstChild).toBeInTheDocument();
486
+ });
487
+
488
+ it('handles vertical lines', () => {
489
+ const { container } = renderComponent({
490
+ from: xy(1, 0),
491
+ to: xy(1, 5),
492
+ });
493
+ expect(container.firstChild).toBeInTheDocument();
494
+ });
495
+
496
+ it('handles horizontal lines', () => {
497
+ const { container } = renderComponent({
498
+ from: xy(0, 1),
499
+ to: xy(5, 1),
500
+ });
501
+ expect(container.firstChild).toBeInTheDocument();
502
+ });
503
+
504
+ it('handles empty label strings', () => {
505
+ const { container } = renderComponent({
506
+ labelNode,
507
+ from: xyLabel(0, 0, ''),
508
+ to: xyLabel(1, 1, ''),
509
+ });
510
+ expect(container.firstChild).toBeInTheDocument();
511
+ });
512
+ });
513
+
514
+ describe('integration scenarios', () => {
515
+ it('renders complete line with all features', () => {
516
+ const { container } = renderComponent({
517
+ from: xyLabel(0, 0, 'Start'),
518
+ to: xyLabel(5, 5, 'End'),
519
+ middle: xyLabel(2.5, 2.5, 'Middle'),
520
+ labelNode,
521
+ coordinatesOnHover: true,
522
+ labelModeEnabled: true,
523
+ disabled: false,
524
+ correctness: 'correct',
525
+ fill: '#00ff00',
526
+ gssLineData: { selectedTool: 'lineA' },
527
+ onDragStart: jest.fn(),
528
+ onDragStop: jest.fn(),
529
+ });
530
+ expect(container.firstChild).toBeInTheDocument();
531
+ });
532
+
533
+ it('renders disabled background line', () => {
534
+ const { container } = renderComponent({
535
+ from: xy(0, 0),
536
+ to: xy(1, 1),
537
+ disabled: true,
538
+ correctness: 'incorrect',
539
+ });
540
+ expect(container.firstChild).toBeInTheDocument();
541
+ });
542
+
543
+ it('renders solution set mode', () => {
544
+ const { container } = renderComponent({
545
+ from: xy(0, 0),
546
+ to: xy(1, 1),
547
+ gssLineData: { selectedTool: 'solutionSet' },
548
+ labelNode,
549
+ });
550
+ expect(container.firstChild).toBeInTheDocument();
551
+ });
109
552
  });
110
553
  });
@@ -1,11 +1,11 @@
1
1
  import { render } from '@pie-lib/test-utils';
2
2
  import React from 'react';
3
3
  import { graphProps as getGraphProps } from '../../../../__tests__/utils';
4
- import { gridDraggable, utils } from '@pie-lib/plot';
5
- const { xy } = utils;
6
-
4
+ import { utils } from '@pie-lib/plot';
7
5
  import * as lineUtils from '../../../../utils';
8
6
 
7
+ const { xy } = utils;
8
+
9
9
  const { bounds, pointsToArea } = lineUtils;
10
10
  jest.mock('../../../../utils', () => {
11
11
  const a = jest.requireActual('../../../../utils');
@@ -39,7 +39,10 @@ describe('LinePath', () => {
39
39
  graphProps: getGraphProps(),
40
40
  from: xy(0, 0, 0),
41
41
  to: xy(1, 1, 0),
42
- data: [[0, 0], [1, 1]],
42
+ data: [
43
+ [0, 0],
44
+ [1, 1],
45
+ ],
43
46
  };
44
47
  const props = { ...defaults, ...extras };
45
48
  return render(<LinePath {...props} />);