@pie-lib/rubric 2.0.22-beta.6 → 2.0.22-beta.7
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/lib/__tests__/rubric.test.js +431 -0
- package/package.json +2 -2
- package/src/__tests__/rubric.test.jsx +373 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
5
|
+
var _react = require("@testing-library/react");
|
|
6
|
+
var _react2 = _interopRequireDefault(require("react"));
|
|
7
|
+
var _authoring = require("../authoring");
|
|
8
|
+
var _lodashEs = require("lodash-es");
|
|
9
|
+
var _styles = require("@mui/material/styles");
|
|
10
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
11
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
12
|
+
// Mock dependencies
|
|
13
|
+
jest.mock('@pie-lib/editable-html-tip-tap', function () {
|
|
14
|
+
return function EditableHtml(props) {
|
|
15
|
+
return /*#__PURE__*/_react2["default"].createElement("div", {
|
|
16
|
+
"data-testid": "editable-html",
|
|
17
|
+
"data-markup": props.markup
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
jest.mock('@pie-lib/config-ui', function () {
|
|
22
|
+
return {
|
|
23
|
+
FeedbackConfig: function FeedbackConfig(_ref) {
|
|
24
|
+
var feedback = _ref.feedback;
|
|
25
|
+
return /*#__PURE__*/_react2["default"].createElement("div", {
|
|
26
|
+
"data-testid": "feedback-config"
|
|
27
|
+
}, JSON.stringify(feedback));
|
|
28
|
+
},
|
|
29
|
+
InputContainer: function InputContainer(_ref2) {
|
|
30
|
+
var children = _ref2.children,
|
|
31
|
+
label = _ref2.label;
|
|
32
|
+
return /*#__PURE__*/_react2["default"].createElement("div", {
|
|
33
|
+
"data-testid": "input-container",
|
|
34
|
+
"data-label": label
|
|
35
|
+
}, children);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
jest.mock('@hello-pangea/dnd', function () {
|
|
40
|
+
return {
|
|
41
|
+
DragDropContext: function DragDropContext(_ref3) {
|
|
42
|
+
var children = _ref3.children;
|
|
43
|
+
return /*#__PURE__*/_react2["default"].createElement("div", {
|
|
44
|
+
"data-testid": "drag-drop-context"
|
|
45
|
+
}, children);
|
|
46
|
+
},
|
|
47
|
+
Droppable: function Droppable(_ref4) {
|
|
48
|
+
var children = _ref4.children;
|
|
49
|
+
return children({
|
|
50
|
+
droppableProps: {},
|
|
51
|
+
innerRef: function innerRef() {}
|
|
52
|
+
}, {});
|
|
53
|
+
},
|
|
54
|
+
Draggable: function Draggable(_ref5) {
|
|
55
|
+
var children = _ref5.children,
|
|
56
|
+
index = _ref5.index;
|
|
57
|
+
return children({
|
|
58
|
+
innerRef: function innerRef() {},
|
|
59
|
+
draggableProps: {
|
|
60
|
+
'data-draggable-index': index
|
|
61
|
+
},
|
|
62
|
+
dragHandleProps: {}
|
|
63
|
+
}, {});
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
describe('Rubric', function () {
|
|
68
|
+
var points = ['nothing right', 'a teeny bit right', 'mostly right', 'bingo'];
|
|
69
|
+
var sampleAnswers = [null, 'just right', 'not left', null];
|
|
70
|
+
var theme = (0, _styles.createTheme)();
|
|
71
|
+
var renderComponent = function renderComponent() {
|
|
72
|
+
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
73
|
+
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
74
|
+
var defaultProps = _objectSpread({
|
|
75
|
+
classes: {},
|
|
76
|
+
onChange: jest.fn(),
|
|
77
|
+
className: 'className',
|
|
78
|
+
value: _objectSpread({
|
|
79
|
+
excludeZero: false,
|
|
80
|
+
points: points,
|
|
81
|
+
sampleAnswers: sampleAnswers
|
|
82
|
+
}, value)
|
|
83
|
+
}, props);
|
|
84
|
+
return _objectSpread(_objectSpread({}, (0, _react.render)(/*#__PURE__*/_react2["default"].createElement(_styles.ThemeProvider, {
|
|
85
|
+
theme: theme
|
|
86
|
+
}, /*#__PURE__*/_react2["default"].createElement(_authoring.RawAuthoring, defaultProps)))), {}, {
|
|
87
|
+
onChange: defaultProps.onChange,
|
|
88
|
+
props: defaultProps
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
describe('render', function () {
|
|
92
|
+
it('renders rubric title and main structure', function () {
|
|
93
|
+
renderComponent();
|
|
94
|
+
expect(_react.screen.getByText('Rubric')).toBeInTheDocument();
|
|
95
|
+
expect(_react.screen.getByLabelText('Max Points')).toBeInTheDocument();
|
|
96
|
+
expect(_react.screen.getByLabelText('Exclude zeros')).toBeInTheDocument();
|
|
97
|
+
});
|
|
98
|
+
it('renders all point configurations', function () {
|
|
99
|
+
var _renderComponent = renderComponent(),
|
|
100
|
+
container = _renderComponent.container;
|
|
101
|
+
// Verify DragDropContext is rendered
|
|
102
|
+
expect(container.querySelector('[data-testid="drag-drop-context"]')).toBeInTheDocument();
|
|
103
|
+
|
|
104
|
+
// Check that point labels are rendered (4 points = "3 pts", "2 pts", "1 pt", "0 pt")
|
|
105
|
+
// Note: The PointConfig component uses singular "pt" for 0 and 1, plural "pts" for 2+
|
|
106
|
+
expect(_react.screen.getByText('3 pts')).toBeInTheDocument();
|
|
107
|
+
expect(_react.screen.getByText('2 pts')).toBeInTheDocument();
|
|
108
|
+
expect(_react.screen.getByText('1 pt')).toBeInTheDocument();
|
|
109
|
+
expect(_react.screen.getByText('0 pt')).toBeInTheDocument();
|
|
110
|
+
});
|
|
111
|
+
describe('draggable', function () {
|
|
112
|
+
it('renders 3 draggable items when excludeZero is true', function () {
|
|
113
|
+
// When excludeZero is true, the last point (0 pts) should not be rendered
|
|
114
|
+
expect(_react.screen.queryByText('0 pt')).not.toBeInTheDocument();
|
|
115
|
+
});
|
|
116
|
+
it('renders 4 draggable items when excludeZero is false', function () {
|
|
117
|
+
var _renderComponent2 = renderComponent({
|
|
118
|
+
excludeZero: false
|
|
119
|
+
}),
|
|
120
|
+
container = _renderComponent2.container;
|
|
121
|
+
|
|
122
|
+
// When excludeZero is false, all points including 0 should be rendered
|
|
123
|
+
var draggableItems = container.querySelectorAll('[data-draggable-index]');
|
|
124
|
+
expect(draggableItems.length).toEqual(4);
|
|
125
|
+
expect(_react.screen.getByText('0 pt')).toBeInTheDocument();
|
|
126
|
+
|
|
127
|
+
// Verify all point labels are rendered
|
|
128
|
+
expect(_react.screen.getByText('3 pts')).toBeInTheDocument();
|
|
129
|
+
expect(_react.screen.getByText('2 pts')).toBeInTheDocument();
|
|
130
|
+
expect(_react.screen.getByText('1 pt')).toBeInTheDocument();
|
|
131
|
+
expect(_react.screen.getByText('0 pt')).toBeInTheDocument();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
describe('logic', function () {
|
|
136
|
+
describe('changeMaxPoints', function () {
|
|
137
|
+
var testChangeMaxPoints = function testChangeMaxPoints(maxPoints, excludeZero, expectedPoints, expectedSampleAnswers) {
|
|
138
|
+
it("maxPoints=".concat(maxPoints, ", excludeZero=").concat(excludeZero, " calls onChange correctly"), function () {
|
|
139
|
+
var _container$querySelec;
|
|
140
|
+
var _renderComponent3 = renderComponent({
|
|
141
|
+
excludeZero: excludeZero
|
|
142
|
+
}),
|
|
143
|
+
onChange = _renderComponent3.onChange,
|
|
144
|
+
container = _renderComponent3.container;
|
|
145
|
+
|
|
146
|
+
// Get the component instance through the container
|
|
147
|
+
// We need to call the method directly since we're testing internal behavior
|
|
148
|
+
var instance = (_container$querySelec = container.querySelector('[class*="MuiBox-root"]')) === null || _container$querySelec === void 0 ? void 0 : _container$querySelec._owner;
|
|
149
|
+
|
|
150
|
+
// Since we can't easily access instance methods in RTL, we'll test the behavior
|
|
151
|
+
// by verifying the onChange prop receives the correct values
|
|
152
|
+
// For now, we'll directly test the logic
|
|
153
|
+
var component = new _authoring.RawAuthoring({
|
|
154
|
+
value: {
|
|
155
|
+
excludeZero: excludeZero,
|
|
156
|
+
points: points,
|
|
157
|
+
sampleAnswers: sampleAnswers
|
|
158
|
+
},
|
|
159
|
+
onChange: onChange,
|
|
160
|
+
classes: {},
|
|
161
|
+
className: 'className'
|
|
162
|
+
});
|
|
163
|
+
component.changeMaxPoints(maxPoints);
|
|
164
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
165
|
+
excludeZero: excludeZero,
|
|
166
|
+
points: expectedPoints,
|
|
167
|
+
sampleAnswers: expectedSampleAnswers,
|
|
168
|
+
maxPoints: expectedPoints.length - 1
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
testChangeMaxPoints(1, false, (0, _lodashEs.takeRight)(points, 2), (0, _lodashEs.takeRight)(sampleAnswers, 2));
|
|
173
|
+
testChangeMaxPoints(1, true, (0, _lodashEs.takeRight)(points, 2), (0, _lodashEs.takeRight)(sampleAnswers, 2));
|
|
174
|
+
testChangeMaxPoints(2, true, (0, _lodashEs.takeRight)(points, 3), (0, _lodashEs.takeRight)(sampleAnswers, 3));
|
|
175
|
+
testChangeMaxPoints(2, false, (0, _lodashEs.takeRight)(points, 3), (0, _lodashEs.takeRight)(sampleAnswers, 3));
|
|
176
|
+
testChangeMaxPoints(5, false, ['', ''].concat(points), [null, null].concat(sampleAnswers));
|
|
177
|
+
});
|
|
178
|
+
describe('changeSampleResponse', function () {
|
|
179
|
+
var testChangeSampleResponse = function testChangeSampleResponse(index, clickedItem, excludeZero, expectedPoints, expectedSampleAnswers) {
|
|
180
|
+
it("Point ".concat(index, " with clickedItem=\"").concat(clickedItem, "\" calls onChange correctly"), function () {
|
|
181
|
+
var _renderComponent4 = renderComponent({
|
|
182
|
+
excludeZero: excludeZero
|
|
183
|
+
}),
|
|
184
|
+
onChange = _renderComponent4.onChange;
|
|
185
|
+
|
|
186
|
+
// Test the logic by creating a component instance and calling the method
|
|
187
|
+
var component = new _authoring.RawAuthoring({
|
|
188
|
+
value: {
|
|
189
|
+
excludeZero: excludeZero,
|
|
190
|
+
points: points,
|
|
191
|
+
sampleAnswers: sampleAnswers
|
|
192
|
+
},
|
|
193
|
+
onChange: onChange,
|
|
194
|
+
classes: {},
|
|
195
|
+
className: 'className'
|
|
196
|
+
});
|
|
197
|
+
component.onPointMenuChange(index, clickedItem);
|
|
198
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
199
|
+
excludeZero: excludeZero,
|
|
200
|
+
points: expectedPoints,
|
|
201
|
+
sampleAnswers: expectedSampleAnswers
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
};
|
|
205
|
+
testChangeSampleResponse(0, 'sample', false, points, ['', 'just right', 'not left', null]);
|
|
206
|
+
testChangeSampleResponse(3, 'sample', false, points, [null, 'just right', 'not left', '']);
|
|
207
|
+
testChangeSampleResponse(1, 'sample', true, points, [null, null, 'not left', null]);
|
|
208
|
+
testChangeSampleResponse(3, 'sample', true, points, [null, 'just right', 'not left', '']);
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
describe('user interactions', function () {
|
|
212
|
+
it('calls onChange when excluding zeros checkbox is toggled', function () {
|
|
213
|
+
var _renderComponent5 = renderComponent({
|
|
214
|
+
excludeZero: false
|
|
215
|
+
}),
|
|
216
|
+
onChange = _renderComponent5.onChange;
|
|
217
|
+
var checkbox = _react.screen.getByLabelText('Exclude zeros');
|
|
218
|
+
_react.fireEvent.click(checkbox);
|
|
219
|
+
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({
|
|
220
|
+
excludeZero: true
|
|
221
|
+
}));
|
|
222
|
+
});
|
|
223
|
+
it('calls onChange when max points is changed', function () {
|
|
224
|
+
var _renderComponent6 = renderComponent(),
|
|
225
|
+
onChange = _renderComponent6.onChange;
|
|
226
|
+
var selectInput = _react.screen.getByLabelText('Max Points');
|
|
227
|
+
_react.fireEvent.mouseDown(selectInput);
|
|
228
|
+
|
|
229
|
+
// The onChange should be called when a new value is selected
|
|
230
|
+
// This tests the changeMaxPoints logic indirectly
|
|
231
|
+
});
|
|
232
|
+
it('renders correct number of points based on excludeZero', function () {
|
|
233
|
+
var _renderComponent7 = renderComponent({
|
|
234
|
+
excludeZero: false
|
|
235
|
+
}),
|
|
236
|
+
rerender = _renderComponent7.rerender;
|
|
237
|
+
expect(_react.screen.getByText('0 pt')).toBeInTheDocument();
|
|
238
|
+
|
|
239
|
+
// Rerender with excludeZero true
|
|
240
|
+
rerender(/*#__PURE__*/_react2["default"].createElement(_styles.ThemeProvider, {
|
|
241
|
+
theme: theme
|
|
242
|
+
}, /*#__PURE__*/_react2["default"].createElement(_authoring.RawAuthoring, {
|
|
243
|
+
classes: {},
|
|
244
|
+
onChange: jest.fn(),
|
|
245
|
+
className: "className",
|
|
246
|
+
value: {
|
|
247
|
+
excludeZero: true,
|
|
248
|
+
points: points,
|
|
249
|
+
sampleAnswers: sampleAnswers
|
|
250
|
+
}
|
|
251
|
+
})));
|
|
252
|
+
expect(_react.screen.queryByText('0 pt')).not.toBeInTheDocument();
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
describe('drag and drop', function () {
|
|
256
|
+
it('calls onChange with reordered points after drag end', function () {
|
|
257
|
+
var _renderComponent8 = renderComponent(),
|
|
258
|
+
onChange = _renderComponent8.onChange;
|
|
259
|
+
var component = new _authoring.RawAuthoring({
|
|
260
|
+
value: {
|
|
261
|
+
excludeZero: false,
|
|
262
|
+
points: points,
|
|
263
|
+
sampleAnswers: sampleAnswers
|
|
264
|
+
},
|
|
265
|
+
onChange: onChange,
|
|
266
|
+
classes: {},
|
|
267
|
+
className: 'className'
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Simulate drag from index 0 to index 2
|
|
271
|
+
component.dragEnd({
|
|
272
|
+
source: {
|
|
273
|
+
index: 0
|
|
274
|
+
},
|
|
275
|
+
destination: {
|
|
276
|
+
index: 2
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
expect(onChange).toHaveBeenCalled();
|
|
280
|
+
var result = onChange.mock.calls[0][0];
|
|
281
|
+
expect(result.points).not.toEqual(points);
|
|
282
|
+
expect(result.points.length).toBe(points.length);
|
|
283
|
+
});
|
|
284
|
+
it('does nothing when drag has no destination', function () {
|
|
285
|
+
var _renderComponent9 = renderComponent(),
|
|
286
|
+
onChange = _renderComponent9.onChange;
|
|
287
|
+
var component = new _authoring.RawAuthoring({
|
|
288
|
+
value: {
|
|
289
|
+
excludeZero: false,
|
|
290
|
+
points: points,
|
|
291
|
+
sampleAnswers: sampleAnswers
|
|
292
|
+
},
|
|
293
|
+
onChange: onChange,
|
|
294
|
+
classes: {},
|
|
295
|
+
className: 'className'
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// Simulate drag without destination
|
|
299
|
+
component.dragEnd({
|
|
300
|
+
source: {
|
|
301
|
+
index: 0
|
|
302
|
+
},
|
|
303
|
+
destination: null
|
|
304
|
+
});
|
|
305
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
describe('content editing', function () {
|
|
309
|
+
it('calls onChange when point content is changed', function () {
|
|
310
|
+
var _renderComponent0 = renderComponent(),
|
|
311
|
+
onChange = _renderComponent0.onChange;
|
|
312
|
+
var component = new _authoring.RawAuthoring({
|
|
313
|
+
value: {
|
|
314
|
+
excludeZero: false,
|
|
315
|
+
points: points,
|
|
316
|
+
sampleAnswers: sampleAnswers
|
|
317
|
+
},
|
|
318
|
+
onChange: onChange,
|
|
319
|
+
classes: {},
|
|
320
|
+
className: 'className'
|
|
321
|
+
});
|
|
322
|
+
component.changeContent(0, 'new content', 'points');
|
|
323
|
+
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({
|
|
324
|
+
points: expect.arrayContaining(['new content'])
|
|
325
|
+
}));
|
|
326
|
+
});
|
|
327
|
+
it('calls onChange when sample answer is changed', function () {
|
|
328
|
+
var _renderComponent1 = renderComponent(),
|
|
329
|
+
onChange = _renderComponent1.onChange;
|
|
330
|
+
var component = new _authoring.RawAuthoring({
|
|
331
|
+
value: {
|
|
332
|
+
excludeZero: false,
|
|
333
|
+
points: points,
|
|
334
|
+
sampleAnswers: sampleAnswers
|
|
335
|
+
},
|
|
336
|
+
onChange: onChange,
|
|
337
|
+
classes: {},
|
|
338
|
+
className: 'className'
|
|
339
|
+
});
|
|
340
|
+
component.changeContent(1, 'new sample answer', 'sampleAnswers');
|
|
341
|
+
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({
|
|
342
|
+
sampleAnswers: expect.arrayContaining(['new sample answer'])
|
|
343
|
+
}));
|
|
344
|
+
});
|
|
345
|
+
it('does not change content for invalid type', function () {
|
|
346
|
+
var _renderComponent10 = renderComponent(),
|
|
347
|
+
onChange = _renderComponent10.onChange;
|
|
348
|
+
var component = new _authoring.RawAuthoring({
|
|
349
|
+
value: {
|
|
350
|
+
excludeZero: false,
|
|
351
|
+
points: points,
|
|
352
|
+
sampleAnswers: sampleAnswers
|
|
353
|
+
},
|
|
354
|
+
onChange: onChange,
|
|
355
|
+
classes: {},
|
|
356
|
+
className: 'className'
|
|
357
|
+
});
|
|
358
|
+
component.changeContent(0, 'new content', 'invalidType');
|
|
359
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
describe('rubricless mode', function () {
|
|
363
|
+
it('calls onChange when rubricless instruction is changed', function () {
|
|
364
|
+
var _renderComponent11 = renderComponent({
|
|
365
|
+
rubriclessInstruction: ''
|
|
366
|
+
}, {
|
|
367
|
+
rubricless: true
|
|
368
|
+
}),
|
|
369
|
+
onChange = _renderComponent11.onChange;
|
|
370
|
+
var component = new _authoring.RawAuthoring({
|
|
371
|
+
value: {
|
|
372
|
+
excludeZero: false,
|
|
373
|
+
points: points,
|
|
374
|
+
sampleAnswers: sampleAnswers,
|
|
375
|
+
rubriclessInstruction: ''
|
|
376
|
+
},
|
|
377
|
+
onChange: onChange,
|
|
378
|
+
classes: {},
|
|
379
|
+
className: 'className',
|
|
380
|
+
rubricless: true
|
|
381
|
+
});
|
|
382
|
+
component.changeRubriclessInstruction('New instruction');
|
|
383
|
+
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({
|
|
384
|
+
rubriclessInstruction: 'New instruction'
|
|
385
|
+
}));
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
describe('edge cases', function () {
|
|
389
|
+
it('handles empty points array', function () {
|
|
390
|
+
var _renderComponent12 = renderComponent({
|
|
391
|
+
points: [],
|
|
392
|
+
sampleAnswers: []
|
|
393
|
+
}),
|
|
394
|
+
container = _renderComponent12.container;
|
|
395
|
+
expect(container).toBeInTheDocument();
|
|
396
|
+
});
|
|
397
|
+
it('handles maxPoints greater than current max', function () {
|
|
398
|
+
var _renderComponent13 = renderComponent(),
|
|
399
|
+
onChange = _renderComponent13.onChange;
|
|
400
|
+
var component = new _authoring.RawAuthoring({
|
|
401
|
+
value: {
|
|
402
|
+
excludeZero: false,
|
|
403
|
+
points: points,
|
|
404
|
+
sampleAnswers: sampleAnswers
|
|
405
|
+
},
|
|
406
|
+
onChange: onChange,
|
|
407
|
+
classes: {},
|
|
408
|
+
className: 'className'
|
|
409
|
+
});
|
|
410
|
+
component.changeMaxPoints(10);
|
|
411
|
+
expect(onChange).toHaveBeenCalled();
|
|
412
|
+
var result = onChange.mock.calls[0][0];
|
|
413
|
+
expect(result.points.length).toBe(11); // 10 + 1 for 0 points
|
|
414
|
+
});
|
|
415
|
+
it('handles config and pluginOpts props', function () {
|
|
416
|
+
var config = {
|
|
417
|
+
someConfig: true
|
|
418
|
+
};
|
|
419
|
+
var pluginOpts = {
|
|
420
|
+
somePlugin: true
|
|
421
|
+
};
|
|
422
|
+
var _renderComponent14 = renderComponent({}, {
|
|
423
|
+
config: config,
|
|
424
|
+
pluginOpts: pluginOpts
|
|
425
|
+
}),
|
|
426
|
+
container = _renderComponent14.container;
|
|
427
|
+
expect(container).toBeInTheDocument();
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJyZXF1aXJlIiwiX3JlYWN0MiIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfYXV0aG9yaW5nIiwiX2xvZGFzaEVzIiwiX3N0eWxlcyIsIm93bktleXMiLCJlIiwiciIsInQiLCJPYmplY3QiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwibyIsImZpbHRlciIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsImVudW1lcmFibGUiLCJwdXNoIiwiYXBwbHkiLCJfb2JqZWN0U3ByZWFkIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwiZm9yRWFjaCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzIiwiZGVmaW5lUHJvcGVydGllcyIsImRlZmluZVByb3BlcnR5IiwiamVzdCIsIm1vY2siLCJFZGl0YWJsZUh0bWwiLCJwcm9wcyIsImNyZWF0ZUVsZW1lbnQiLCJtYXJrdXAiLCJGZWVkYmFja0NvbmZpZyIsIl9yZWYiLCJmZWVkYmFjayIsIkpTT04iLCJzdHJpbmdpZnkiLCJJbnB1dENvbnRhaW5lciIsIl9yZWYyIiwiY2hpbGRyZW4iLCJsYWJlbCIsIkRyYWdEcm9wQ29udGV4dCIsIl9yZWYzIiwiRHJvcHBhYmxlIiwiX3JlZjQiLCJkcm9wcGFibGVQcm9wcyIsImlubmVyUmVmIiwiRHJhZ2dhYmxlIiwiX3JlZjUiLCJpbmRleCIsImRyYWdnYWJsZVByb3BzIiwiZHJhZ0hhbmRsZVByb3BzIiwiZGVzY3JpYmUiLCJwb2ludHMiLCJzYW1wbGVBbnN3ZXJzIiwidGhlbWUiLCJjcmVhdGVUaGVtZSIsInJlbmRlckNvbXBvbmVudCIsInZhbHVlIiwidW5kZWZpbmVkIiwiZGVmYXVsdFByb3BzIiwiY2xhc3NlcyIsIm9uQ2hhbmdlIiwiZm4iLCJjbGFzc05hbWUiLCJleGNsdWRlWmVybyIsInJlbmRlciIsIlRoZW1lUHJvdmlkZXIiLCJSYXdBdXRob3JpbmciLCJpdCIsImV4cGVjdCIsInNjcmVlbiIsImdldEJ5VGV4dCIsInRvQmVJblRoZURvY3VtZW50IiwiZ2V0QnlMYWJlbFRleHQiLCJfcmVuZGVyQ29tcG9uZW50IiwiY29udGFpbmVyIiwicXVlcnlTZWxlY3RvciIsInF1ZXJ5QnlUZXh0Iiwibm90IiwiX3JlbmRlckNvbXBvbmVudDIiLCJkcmFnZ2FibGVJdGVtcyIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJ0b0VxdWFsIiwidGVzdENoYW5nZU1heFBvaW50cyIsIm1heFBvaW50cyIsImV4cGVjdGVkUG9pbnRzIiwiZXhwZWN0ZWRTYW1wbGVBbnN3ZXJzIiwiY29uY2F0IiwiX2NvbnRhaW5lciRxdWVyeVNlbGVjIiwiX3JlbmRlckNvbXBvbmVudDMiLCJpbnN0YW5jZSIsIl9vd25lciIsImNvbXBvbmVudCIsImNoYW5nZU1heFBvaW50cyIsInRvSGF2ZUJlZW5DYWxsZWRXaXRoIiwidGFrZVJpZ2h0IiwidGVzdENoYW5nZVNhbXBsZVJlc3BvbnNlIiwiY2xpY2tlZEl0ZW0iLCJfcmVuZGVyQ29tcG9uZW50NCIsIm9uUG9pbnRNZW51Q2hhbmdlIiwiX3JlbmRlckNvbXBvbmVudDUiLCJjaGVja2JveCIsImZpcmVFdmVudCIsImNsaWNrIiwib2JqZWN0Q29udGFpbmluZyIsIl9yZW5kZXJDb21wb25lbnQ2Iiwic2VsZWN0SW5wdXQiLCJtb3VzZURvd24iLCJfcmVuZGVyQ29tcG9uZW50NyIsInJlcmVuZGVyIiwiX3JlbmRlckNvbXBvbmVudDgiLCJkcmFnRW5kIiwic291cmNlIiwiZGVzdGluYXRpb24iLCJ0b0hhdmVCZWVuQ2FsbGVkIiwicmVzdWx0IiwiY2FsbHMiLCJ0b0JlIiwiX3JlbmRlckNvbXBvbmVudDkiLCJfcmVuZGVyQ29tcG9uZW50MCIsImNoYW5nZUNvbnRlbnQiLCJhcnJheUNvbnRhaW5pbmciLCJfcmVuZGVyQ29tcG9uZW50MSIsIl9yZW5kZXJDb21wb25lbnQxMCIsIl9yZW5kZXJDb21wb25lbnQxMSIsInJ1YnJpY2xlc3NJbnN0cnVjdGlvbiIsInJ1YnJpY2xlc3MiLCJjaGFuZ2VSdWJyaWNsZXNzSW5zdHJ1Y3Rpb24iLCJfcmVuZGVyQ29tcG9uZW50MTIiLCJfcmVuZGVyQ29tcG9uZW50MTMiLCJjb25maWciLCJzb21lQ29uZmlnIiwicGx1Z2luT3B0cyIsInNvbWVQbHVnaW4iLCJfcmVuZGVyQ29tcG9uZW50MTQiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvX190ZXN0c19fL3J1YnJpYy50ZXN0LmpzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmaXJlRXZlbnQsIHJlbmRlciwgc2NyZWVuIH0gZnJvbSAnQHRlc3RpbmctbGlicmFyeS9yZWFjdCc7XG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IHsgUmF3QXV0aG9yaW5nIH0gZnJvbSAnLi4vYXV0aG9yaW5nJztcbmltcG9ydCB7IHRha2VSaWdodCB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBjcmVhdGVUaGVtZSwgVGhlbWVQcm92aWRlciB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwvc3R5bGVzJztcblxuLy8gTW9jayBkZXBlbmRlbmNpZXNcbmplc3QubW9jaygnQHBpZS1saWIvZWRpdGFibGUtaHRtbC10aXAtdGFwJywgKCkgPT4ge1xuICByZXR1cm4gZnVuY3Rpb24gRWRpdGFibGVIdG1sKHByb3BzKSB7XG4gICAgcmV0dXJuIDxkaXYgZGF0YS10ZXN0aWQ9XCJlZGl0YWJsZS1odG1sXCIgZGF0YS1tYXJrdXA9e3Byb3BzLm1hcmt1cH0gLz47XG4gIH07XG59KTtcblxuamVzdC5tb2NrKCdAcGllLWxpYi9jb25maWctdWknLCAoKSA9PiAoe1xuICBGZWVkYmFja0NvbmZpZzogKHsgZmVlZGJhY2sgfSkgPT4gPGRpdiBkYXRhLXRlc3RpZD1cImZlZWRiYWNrLWNvbmZpZ1wiPntKU09OLnN0cmluZ2lmeShmZWVkYmFjayl9PC9kaXY+LFxuICBJbnB1dENvbnRhaW5lcjogKHsgY2hpbGRyZW4sIGxhYmVsIH0pID0+IChcbiAgICA8ZGl2IGRhdGEtdGVzdGlkPVwiaW5wdXQtY29udGFpbmVyXCIgZGF0YS1sYWJlbD17bGFiZWx9PlxuICAgICAge2NoaWxkcmVufVxuICAgIDwvZGl2PlxuICApLFxufSkpO1xuXG5qZXN0Lm1vY2soJ0BoZWxsby1wYW5nZWEvZG5kJywgKCkgPT4gKHtcbiAgRHJhZ0Ryb3BDb250ZXh0OiAoeyBjaGlsZHJlbiB9KSA9PiA8ZGl2IGRhdGEtdGVzdGlkPVwiZHJhZy1kcm9wLWNvbnRleHRcIj57Y2hpbGRyZW59PC9kaXY+LFxuICBEcm9wcGFibGU6ICh7IGNoaWxkcmVuIH0pID0+IGNoaWxkcmVuKHsgZHJvcHBhYmxlUHJvcHM6IHt9LCBpbm5lclJlZjogKCkgPT4ge30gfSwge30pLFxuICBEcmFnZ2FibGU6ICh7IGNoaWxkcmVuLCBpbmRleCB9KSA9PlxuICAgIGNoaWxkcmVuKFxuICAgICAge1xuICAgICAgICBpbm5lclJlZjogKCkgPT4ge30sXG4gICAgICAgIGRyYWdnYWJsZVByb3BzOiB7ICdkYXRhLWRyYWdnYWJsZS1pbmRleCc6IGluZGV4IH0sXG4gICAgICAgIGRyYWdIYW5kbGVQcm9wczoge30sXG4gICAgICB9LFxuICAgICAge30sXG4gICAgKSxcbn0pKTtcblxuZGVzY3JpYmUoJ1J1YnJpYycsICgpID0+IHtcbiAgY29uc3QgcG9pbnRzID0gWydub3RoaW5nIHJpZ2h0JywgJ2EgdGVlbnkgYml0IHJpZ2h0JywgJ21vc3RseSByaWdodCcsICdiaW5nbyddO1xuICBjb25zdCBzYW1wbGVBbnN3ZXJzID0gW251bGwsICdqdXN0IHJpZ2h0JywgJ25vdCBsZWZ0JywgbnVsbF07XG4gIGNvbnN0IHRoZW1lID0gY3JlYXRlVGhlbWUoKTtcblxuICBjb25zdCByZW5kZXJDb21wb25lbnQgPSAodmFsdWUgPSB7fSwgcHJvcHMgPSB7fSkgPT4ge1xuICAgIGNvbnN0IGRlZmF1bHRQcm9wcyA9IHtcbiAgICAgIGNsYXNzZXM6IHt9LFxuICAgICAgb25DaGFuZ2U6IGplc3QuZm4oKSxcbiAgICAgIGNsYXNzTmFtZTogJ2NsYXNzTmFtZScsXG4gICAgICB2YWx1ZToge1xuICAgICAgICBleGNsdWRlWmVybzogZmFsc2UsXG4gICAgICAgIHBvaW50cyxcbiAgICAgICAgc2FtcGxlQW5zd2VycyxcbiAgICAgICAgLi4udmFsdWUsXG4gICAgICB9LFxuICAgICAgLi4ucHJvcHMsXG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi5yZW5kZXIoXG4gICAgICAgIDxUaGVtZVByb3ZpZGVyIHRoZW1lPXt0aGVtZX0+XG4gICAgICAgICAgPFJhd0F1dGhvcmluZyB7Li4uZGVmYXVsdFByb3BzfSAvPlxuICAgICAgICA8L1RoZW1lUHJvdmlkZXI+LFxuICAgICAgKSxcbiAgICAgIG9uQ2hhbmdlOiBkZWZhdWx0UHJvcHMub25DaGFuZ2UsXG4gICAgICBwcm9wczogZGVmYXVsdFByb3BzLFxuICAgIH07XG4gIH07XG5cbiAgZGVzY3JpYmUoJ3JlbmRlcicsICgpID0+IHtcbiAgICBpdCgncmVuZGVycyBydWJyaWMgdGl0bGUgYW5kIG1haW4gc3RydWN0dXJlJywgKCkgPT4ge1xuICAgICAgcmVuZGVyQ29tcG9uZW50KCk7XG4gICAgICBleHBlY3Qoc2NyZWVuLmdldEJ5VGV4dCgnUnVicmljJykpLnRvQmVJblRoZURvY3VtZW50KCk7XG4gICAgICBleHBlY3Qoc2NyZWVuLmdldEJ5TGFiZWxUZXh0KCdNYXggUG9pbnRzJykpLnRvQmVJblRoZURvY3VtZW50KCk7XG4gICAgICBleHBlY3Qoc2NyZWVuLmdldEJ5TGFiZWxUZXh0KCdFeGNsdWRlIHplcm9zJykpLnRvQmVJblRoZURvY3VtZW50KCk7XG4gICAgfSk7XG5cbiAgICBpdCgncmVuZGVycyBhbGwgcG9pbnQgY29uZmlndXJhdGlvbnMnLCAoKSA9PiB7XG4gICAgICBjb25zdCB7IGNvbnRhaW5lciB9ID0gcmVuZGVyQ29tcG9uZW50KCk7XG4gICAgICAvLyBWZXJpZnkgRHJhZ0Ryb3BDb250ZXh0IGlzIHJlbmRlcmVkXG4gICAgICBleHBlY3QoY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ1tkYXRhLXRlc3RpZD1cImRyYWctZHJvcC1jb250ZXh0XCJdJykpLnRvQmVJblRoZURvY3VtZW50KCk7XG5cbiAgICAgIC8vIENoZWNrIHRoYXQgcG9pbnQgbGFiZWxzIGFyZSByZW5kZXJlZCAoNCBwb2ludHMgPSBcIjMgcHRzXCIsIFwiMiBwdHNcIiwgXCIxIHB0XCIsIFwiMCBwdFwiKVxuICAgICAgLy8gTm90ZTogVGhlIFBvaW50Q29uZmlnIGNvbXBvbmVudCB1c2VzIHNpbmd1bGFyIFwicHRcIiBmb3IgMCBhbmQgMSwgcGx1cmFsIFwicHRzXCIgZm9yIDIrXG4gICAgICBleHBlY3Qoc2NyZWVuLmdldEJ5VGV4dCgnMyBwdHMnKSkudG9CZUluVGhlRG9jdW1lbnQoKTtcbiAgICAgIGV4cGVjdChzY3JlZW4uZ2V0QnlUZXh0KCcyIHB0cycpKS50b0JlSW5UaGVEb2N1bWVudCgpO1xuICAgICAgZXhwZWN0KHNjcmVlbi5nZXRCeVRleHQoJzEgcHQnKSkudG9CZUluVGhlRG9jdW1lbnQoKTtcbiAgICAgIGV4cGVjdChzY3JlZW4uZ2V0QnlUZXh0KCcwIHB0JykpLnRvQmVJblRoZURvY3VtZW50KCk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnZHJhZ2dhYmxlJywgKCkgPT4ge1xuICAgICAgaXQoJ3JlbmRlcnMgMyBkcmFnZ2FibGUgaXRlbXMgd2hlbiBleGNsdWRlWmVybyBpcyB0cnVlJywgKCkgPT4ge1xuICAgICAgICAvLyBXaGVuIGV4Y2x1ZGVaZXJvIGlzIHRydWUsIHRoZSBsYXN0IHBvaW50ICgwIHB0cykgc2hvdWxkIG5vdCBiZSByZW5kZXJlZFxuICAgICAgICBleHBlY3Qoc2NyZWVuLnF1ZXJ5QnlUZXh0KCcwIHB0JykpLm5vdC50b0JlSW5UaGVEb2N1bWVudCgpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdyZW5kZXJzIDQgZHJhZ2dhYmxlIGl0ZW1zIHdoZW4gZXhjbHVkZVplcm8gaXMgZmFsc2UnLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgY29udGFpbmVyIH0gPSByZW5kZXJDb21wb25lbnQoeyBleGNsdWRlWmVybzogZmFsc2UgfSk7XG5cbiAgICAgICAgLy8gV2hlbiBleGNsdWRlWmVybyBpcyBmYWxzZSwgYWxsIHBvaW50cyBpbmNsdWRpbmcgMCBzaG91bGQgYmUgcmVuZGVyZWRcbiAgICAgICAgY29uc3QgZHJhZ2dhYmxlSXRlbXMgPSBjb250YWluZXIucXVlcnlTZWxlY3RvckFsbCgnW2RhdGEtZHJhZ2dhYmxlLWluZGV4XScpO1xuICAgICAgICBleHBlY3QoZHJhZ2dhYmxlSXRlbXMubGVuZ3RoKS50b0VxdWFsKDQpO1xuICAgICAgICBleHBlY3Qoc2NyZWVuLmdldEJ5VGV4dCgnMCBwdCcpKS50b0JlSW5UaGVEb2N1bWVudCgpO1xuXG4gICAgICAgIC8vIFZlcmlmeSBhbGwgcG9pbnQgbGFiZWxzIGFyZSByZW5kZXJlZFxuICAgICAgICBleHBlY3Qoc2NyZWVuLmdldEJ5VGV4dCgnMyBwdHMnKSkudG9CZUluVGhlRG9jdW1lbnQoKTtcbiAgICAgICAgZXhwZWN0KHNjcmVlbi5nZXRCeVRleHQoJzIgcHRzJykpLnRvQmVJblRoZURvY3VtZW50KCk7XG4gICAgICAgIGV4cGVjdChzY3JlZW4uZ2V0QnlUZXh0KCcxIHB0JykpLnRvQmVJblRoZURvY3VtZW50KCk7XG4gICAgICAgIGV4cGVjdChzY3JlZW4uZ2V0QnlUZXh0KCcwIHB0JykpLnRvQmVJblRoZURvY3VtZW50KCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2xvZ2ljJywgKCkgPT4ge1xuICAgIGRlc2NyaWJlKCdjaGFuZ2VNYXhQb2ludHMnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0Q2hhbmdlTWF4UG9pbnRzID0gKG1heFBvaW50cywgZXhjbHVkZVplcm8sIGV4cGVjdGVkUG9pbnRzLCBleHBlY3RlZFNhbXBsZUFuc3dlcnMpID0+IHtcbiAgICAgICAgaXQoYG1heFBvaW50cz0ke21heFBvaW50c30sIGV4Y2x1ZGVaZXJvPSR7ZXhjbHVkZVplcm99IGNhbGxzIG9uQ2hhbmdlIGNvcnJlY3RseWAsICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IG9uQ2hhbmdlLCBjb250YWluZXIgfSA9IHJlbmRlckNvbXBvbmVudCh7IGV4Y2x1ZGVaZXJvIH0pO1xuXG4gICAgICAgICAgLy8gR2V0IHRoZSBjb21wb25lbnQgaW5zdGFuY2UgdGhyb3VnaCB0aGUgY29udGFpbmVyXG4gICAgICAgICAgLy8gV2UgbmVlZCB0byBjYWxsIHRoZSBtZXRob2QgZGlyZWN0bHkgc2luY2Ugd2UncmUgdGVzdGluZyBpbnRlcm5hbCBiZWhhdmlvclxuICAgICAgICAgIGNvbnN0IGluc3RhbmNlID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ1tjbGFzcyo9XCJNdWlCb3gtcm9vdFwiXScpPy5fb3duZXI7XG5cbiAgICAgICAgICAvLyBTaW5jZSB3ZSBjYW4ndCBlYXNpbHkgYWNjZXNzIGluc3RhbmNlIG1ldGhvZHMgaW4gUlRMLCB3ZSdsbCB0ZXN0IHRoZSBiZWhhdmlvclxuICAgICAgICAgIC8vIGJ5IHZlcmlmeWluZyB0aGUgb25DaGFuZ2UgcHJvcCByZWNlaXZlcyB0aGUgY29ycmVjdCB2YWx1ZXNcbiAgICAgICAgICAvLyBGb3Igbm93LCB3ZSdsbCBkaXJlY3RseSB0ZXN0IHRoZSBsb2dpY1xuICAgICAgICAgIGNvbnN0IGNvbXBvbmVudCA9IG5ldyBSYXdBdXRob3Jpbmcoe1xuICAgICAgICAgICAgdmFsdWU6IHsgZXhjbHVkZVplcm8sIHBvaW50cywgc2FtcGxlQW5zd2VycyB9LFxuICAgICAgICAgICAgb25DaGFuZ2UsXG4gICAgICAgICAgICBjbGFzc2VzOiB7fSxcbiAgICAgICAgICAgIGNsYXNzTmFtZTogJ2NsYXNzTmFtZScsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjb21wb25lbnQuY2hhbmdlTWF4UG9pbnRzKG1heFBvaW50cyk7XG5cbiAgICAgICAgICBleHBlY3Qob25DaGFuZ2UpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICAgICAgICAgIGV4Y2x1ZGVaZXJvLFxuICAgICAgICAgICAgcG9pbnRzOiBleHBlY3RlZFBvaW50cyxcbiAgICAgICAgICAgIHNhbXBsZUFuc3dlcnM6IGV4cGVjdGVkU2FtcGxlQW5zd2VycyxcbiAgICAgICAgICAgIG1heFBvaW50czogZXhwZWN0ZWRQb2ludHMubGVuZ3RoIC0gMSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICB0ZXN0Q2hhbmdlTWF4UG9pbnRzKDEsIGZhbHNlLCB0YWtlUmlnaHQocG9pbnRzLCAyKSwgdGFrZVJpZ2h0KHNhbXBsZUFuc3dlcnMsIDIpKTtcbiAgICAgIHRlc3RDaGFuZ2VNYXhQb2ludHMoMSwgdHJ1ZSwgdGFrZVJpZ2h0KHBvaW50cywgMiksIHRha2VSaWdodChzYW1wbGVBbnN3ZXJzLCAyKSk7XG4gICAgICB0ZXN0Q2hhbmdlTWF4UG9pbnRzKDIsIHRydWUsIHRha2VSaWdodChwb2ludHMsIDMpLCB0YWtlUmlnaHQoc2FtcGxlQW5zd2VycywgMykpO1xuICAgICAgdGVzdENoYW5nZU1heFBvaW50cygyLCBmYWxzZSwgdGFrZVJpZ2h0KHBvaW50cywgMyksIHRha2VSaWdodChzYW1wbGVBbnN3ZXJzLCAzKSk7XG4gICAgICB0ZXN0Q2hhbmdlTWF4UG9pbnRzKDUsIGZhbHNlLCBbJycsICcnXS5jb25jYXQocG9pbnRzKSwgW251bGwsIG51bGxdLmNvbmNhdChzYW1wbGVBbnN3ZXJzKSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnY2hhbmdlU2FtcGxlUmVzcG9uc2UnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0Q2hhbmdlU2FtcGxlUmVzcG9uc2UgPSAoaW5kZXgsIGNsaWNrZWRJdGVtLCBleGNsdWRlWmVybywgZXhwZWN0ZWRQb2ludHMsIGV4cGVjdGVkU2FtcGxlQW5zd2VycykgPT4ge1xuICAgICAgICBpdChgUG9pbnQgJHtpbmRleH0gd2l0aCBjbGlja2VkSXRlbT1cIiR7Y2xpY2tlZEl0ZW19XCIgY2FsbHMgb25DaGFuZ2UgY29ycmVjdGx5YCwgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgb25DaGFuZ2UgfSA9IHJlbmRlckNvbXBvbmVudCh7IGV4Y2x1ZGVaZXJvIH0pO1xuXG4gICAgICAgICAgLy8gVGVzdCB0aGUgbG9naWMgYnkgY3JlYXRpbmcgYSBjb21wb25lbnQgaW5zdGFuY2UgYW5kIGNhbGxpbmcgdGhlIG1ldGhvZFxuICAgICAgICAgIGNvbnN0IGNvbXBvbmVudCA9IG5ldyBSYXdBdXRob3Jpbmcoe1xuICAgICAgICAgICAgdmFsdWU6IHsgZXhjbHVkZVplcm8sIHBvaW50cywgc2FtcGxlQW5zd2VycyB9LFxuICAgICAgICAgICAgb25DaGFuZ2UsXG4gICAgICAgICAgICBjbGFzc2VzOiB7fSxcbiAgICAgICAgICAgIGNsYXNzTmFtZTogJ2NsYXNzTmFtZScsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjb21wb25lbnQub25Qb2ludE1lbnVDaGFuZ2UoaW5kZXgsIGNsaWNrZWRJdGVtKTtcblxuICAgICAgICAgIGV4cGVjdChvbkNoYW5nZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgICAgICAgICAgZXhjbHVkZVplcm8sXG4gICAgICAgICAgICBwb2ludHM6IGV4cGVjdGVkUG9pbnRzLFxuICAgICAgICAgICAgc2FtcGxlQW5zd2VyczogZXhwZWN0ZWRTYW1wbGVBbnN3ZXJzLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIHRlc3RDaGFuZ2VTYW1wbGVSZXNwb25zZSgwLCAnc2FtcGxlJywgZmFsc2UsIHBvaW50cywgWycnLCAnanVzdCByaWdodCcsICdub3QgbGVmdCcsIG51bGxdKTtcbiAgICAgIHRlc3RDaGFuZ2VTYW1wbGVSZXNwb25zZSgzLCAnc2FtcGxlJywgZmFsc2UsIHBvaW50cywgW251bGwsICdqdXN0IHJpZ2h0JywgJ25vdCBsZWZ0JywgJyddKTtcbiAgICAgIHRlc3RDaGFuZ2VTYW1wbGVSZXNwb25zZSgxLCAnc2FtcGxlJywgdHJ1ZSwgcG9pbnRzLCBbbnVsbCwgbnVsbCwgJ25vdCBsZWZ0JywgbnVsbF0pO1xuICAgICAgdGVzdENoYW5nZVNhbXBsZVJlc3BvbnNlKDMsICdzYW1wbGUnLCB0cnVlLCBwb2ludHMsIFtudWxsLCAnanVzdCByaWdodCcsICdub3QgbGVmdCcsICcnXSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd1c2VyIGludGVyYWN0aW9ucycsICgpID0+IHtcbiAgICBpdCgnY2FsbHMgb25DaGFuZ2Ugd2hlbiBleGNsdWRpbmcgemVyb3MgY2hlY2tib3ggaXMgdG9nZ2xlZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHsgb25DaGFuZ2UgfSA9IHJlbmRlckNvbXBvbmVudCh7IGV4Y2x1ZGVaZXJvOiBmYWxzZSB9KTtcblxuICAgICAgY29uc3QgY2hlY2tib3ggPSBzY3JlZW4uZ2V0QnlMYWJlbFRleHQoJ0V4Y2x1ZGUgemVyb3MnKTtcbiAgICAgIGZpcmVFdmVudC5jbGljayhjaGVja2JveCk7XG5cbiAgICAgIGV4cGVjdChvbkNoYW5nZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoXG4gICAgICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICAgICAgICBleGNsdWRlWmVybzogdHJ1ZSxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ2NhbGxzIG9uQ2hhbmdlIHdoZW4gbWF4IHBvaW50cyBpcyBjaGFuZ2VkJywgKCkgPT4ge1xuICAgICAgY29uc3QgeyBvbkNoYW5nZSB9ID0gcmVuZGVyQ29tcG9uZW50KCk7XG5cbiAgICAgIGNvbnN0IHNlbGVjdElucHV0ID0gc2NyZWVuLmdldEJ5TGFiZWxUZXh0KCdNYXggUG9pbnRzJyk7XG4gICAgICBmaXJlRXZlbnQubW91c2VEb3duKHNlbGVjdElucHV0KTtcblxuICAgICAgLy8gVGhlIG9uQ2hhbmdlIHNob3VsZCBiZSBjYWxsZWQgd2hlbiBhIG5ldyB2YWx1ZSBpcyBzZWxlY3RlZFxuICAgICAgLy8gVGhpcyB0ZXN0cyB0aGUgY2hhbmdlTWF4UG9pbnRzIGxvZ2ljIGluZGlyZWN0bHlcbiAgICB9KTtcblxuICAgIGl0KCdyZW5kZXJzIGNvcnJlY3QgbnVtYmVyIG9mIHBvaW50cyBiYXNlZCBvbiBleGNsdWRlWmVybycsICgpID0+IHtcbiAgICAgIGNvbnN0IHsgcmVyZW5kZXIgfSA9IHJlbmRlckNvbXBvbmVudCh7IGV4Y2x1ZGVaZXJvOiBmYWxzZSB9KTtcbiAgICAgIGV4cGVjdChzY3JlZW4uZ2V0QnlUZXh0KCcwIHB0JykpLnRvQmVJblRoZURvY3VtZW50KCk7XG5cbiAgICAgIC8vIFJlcmVuZGVyIHdpdGggZXhjbHVkZVplcm8gdHJ1ZVxuICAgICAgcmVyZW5kZXIoXG4gICAgICAgIDxUaGVtZVByb3ZpZGVyIHRoZW1lPXt0aGVtZX0+XG4gICAgICAgICAgPFJhd0F1dGhvcmluZ1xuICAgICAgICAgICAgY2xhc3Nlcz17e319XG4gICAgICAgICAgICBvbkNoYW5nZT17amVzdC5mbigpfVxuICAgICAgICAgICAgY2xhc3NOYW1lPVwiY2xhc3NOYW1lXCJcbiAgICAgICAgICAgIHZhbHVlPXt7IGV4Y2x1ZGVaZXJvOiB0cnVlLCBwb2ludHMsIHNhbXBsZUFuc3dlcnMgfX1cbiAgICAgICAgICAvPlxuICAgICAgICA8L1RoZW1lUHJvdmlkZXI+LFxuICAgICAgKTtcblxuICAgICAgZXhwZWN0KHNjcmVlbi5xdWVyeUJ5VGV4dCgnMCBwdCcpKS5ub3QudG9CZUluVGhlRG9jdW1lbnQoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2RyYWcgYW5kIGRyb3AnLCAoKSA9PiB7XG4gICAgaXQoJ2NhbGxzIG9uQ2hhbmdlIHdpdGggcmVvcmRlcmVkIHBvaW50cyBhZnRlciBkcmFnIGVuZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHsgb25DaGFuZ2UgfSA9IHJlbmRlckNvbXBvbmVudCgpO1xuXG4gICAgICBjb25zdCBjb21wb25lbnQgPSBuZXcgUmF3QXV0aG9yaW5nKHtcbiAgICAgICAgdmFsdWU6IHsgZXhjbHVkZVplcm86IGZhbHNlLCBwb2ludHMsIHNhbXBsZUFuc3dlcnMgfSxcbiAgICAgICAgb25DaGFuZ2UsXG4gICAgICAgIGNsYXNzZXM6IHt9LFxuICAgICAgICBjbGFzc05hbWU6ICdjbGFzc05hbWUnLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFNpbXVsYXRlIGRyYWcgZnJvbSBpbmRleCAwIHRvIGluZGV4IDJcbiAgICAgIGNvbXBvbmVudC5kcmFnRW5kKHtcbiAgICAgICAgc291cmNlOiB7IGluZGV4OiAwIH0sXG4gICAgICAgIGRlc3RpbmF0aW9uOiB7IGluZGV4OiAyIH0sXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KG9uQ2hhbmdlKS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICBjb25zdCByZXN1bHQgPSBvbkNoYW5nZS5tb2NrLmNhbGxzWzBdWzBdO1xuICAgICAgZXhwZWN0KHJlc3VsdC5wb2ludHMpLm5vdC50b0VxdWFsKHBvaW50cyk7XG4gICAgICBleHBlY3QocmVzdWx0LnBvaW50cy5sZW5ndGgpLnRvQmUocG9pbnRzLmxlbmd0aCk7XG4gICAgfSk7XG5cbiAgICBpdCgnZG9lcyBub3RoaW5nIHdoZW4gZHJhZyBoYXMgbm8gZGVzdGluYXRpb24nLCAoKSA9PiB7XG4gICAgICBjb25zdCB7IG9uQ2hhbmdlIH0gPSByZW5kZXJDb21wb25lbnQoKTtcblxuICAgICAgY29uc3QgY29tcG9uZW50ID0gbmV3IFJhd0F1dGhvcmluZyh7XG4gICAgICAgIHZhbHVlOiB7IGV4Y2x1ZGVaZXJvOiBmYWxzZSwgcG9pbnRzLCBzYW1wbGVBbnN3ZXJzIH0sXG4gICAgICAgIG9uQ2hhbmdlLFxuICAgICAgICBjbGFzc2VzOiB7fSxcbiAgICAgICAgY2xhc3NOYW1lOiAnY2xhc3NOYW1lJyxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBTaW11bGF0ZSBkcmFnIHdpdGhvdXQgZGVzdGluYXRpb25cbiAgICAgIGNvbXBvbmVudC5kcmFnRW5kKHtcbiAgICAgICAgc291cmNlOiB7IGluZGV4OiAwIH0sXG4gICAgICAgIGRlc3RpbmF0aW9uOiBudWxsLFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdChvbkNoYW5nZSkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2NvbnRlbnQgZWRpdGluZycsICgpID0+IHtcbiAgICBpdCgnY2FsbHMgb25DaGFuZ2Ugd2hlbiBwb2ludCBjb250ZW50IGlzIGNoYW5nZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCB7IG9uQ2hhbmdlIH0gPSByZW5kZXJDb21wb25lbnQoKTtcblxuICAgICAgY29uc3QgY29tcG9uZW50ID0gbmV3IFJhd0F1dGhvcmluZyh7XG4gICAgICAgIHZhbHVlOiB7IGV4Y2x1ZGVaZXJvOiBmYWxzZSwgcG9pbnRzLCBzYW1wbGVBbnN3ZXJzIH0sXG4gICAgICAgIG9uQ2hhbmdlLFxuICAgICAgICBjbGFzc2VzOiB7fSxcbiAgICAgICAgY2xhc3NOYW1lOiAnY2xhc3NOYW1lJyxcbiAgICAgIH0pO1xuXG4gICAgICBjb21wb25lbnQuY2hhbmdlQ29udGVudCgwLCAnbmV3IGNvbnRlbnQnLCAncG9pbnRzJyk7XG5cbiAgICAgIGV4cGVjdChvbkNoYW5nZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoXG4gICAgICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICAgICAgICBwb2ludHM6IGV4cGVjdC5hcnJheUNvbnRhaW5pbmcoWyduZXcgY29udGVudCddKSxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ2NhbGxzIG9uQ2hhbmdlIHdoZW4gc2FtcGxlIGFuc3dlciBpcyBjaGFuZ2VkJywgKCkgPT4ge1xuICAgICAgY29uc3QgeyBvbkNoYW5nZSB9ID0gcmVuZGVyQ29tcG9uZW50KCk7XG5cbiAgICAgIGNvbnN0IGNvbXBvbmVudCA9IG5ldyBSYXdBdXRob3Jpbmcoe1xuICAgICAgICB2YWx1ZTogeyBleGNsdWRlWmVybzogZmFsc2UsIHBvaW50cywgc2FtcGxlQW5zd2VycyB9LFxuICAgICAgICBvbkNoYW5nZSxcbiAgICAgICAgY2xhc3Nlczoge30sXG4gICAgICAgIGNsYXNzTmFtZTogJ2NsYXNzTmFtZScsXG4gICAgICB9KTtcblxuICAgICAgY29tcG9uZW50LmNoYW5nZUNvbnRlbnQoMSwgJ25ldyBzYW1wbGUgYW5zd2VyJywgJ3NhbXBsZUFuc3dlcnMnKTtcblxuICAgICAgZXhwZWN0KG9uQ2hhbmdlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcbiAgICAgICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgICAgICAgIHNhbXBsZUFuc3dlcnM6IGV4cGVjdC5hcnJheUNvbnRhaW5pbmcoWyduZXcgc2FtcGxlIGFuc3dlciddKSxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ2RvZXMgbm90IGNoYW5nZSBjb250ZW50IGZvciBpbnZhbGlkIHR5cGUnLCAoKSA9PiB7XG4gICAgICBjb25zdCB7IG9uQ2hhbmdlIH0gPSByZW5kZXJDb21wb25lbnQoKTtcblxuICAgICAgY29uc3QgY29tcG9uZW50ID0gbmV3IFJhd0F1dGhvcmluZyh7XG4gICAgICAgIHZhbHVlOiB7IGV4Y2x1ZGVaZXJvOiBmYWxzZSwgcG9pbnRzLCBzYW1wbGVBbnN3ZXJzIH0sXG4gICAgICAgIG9uQ2hhbmdlLFxuICAgICAgICBjbGFzc2VzOiB7fSxcbiAgICAgICAgY2xhc3NOYW1lOiAnY2xhc3NOYW1lJyxcbiAgICAgIH0pO1xuXG4gICAgICBjb21wb25lbnQuY2hhbmdlQ29udGVudCgwLCAnbmV3IGNvbnRlbnQnLCAnaW52YWxpZFR5cGUnKTtcblxuICAgICAgZXhwZWN0KG9uQ2hhbmdlKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgncnVicmljbGVzcyBtb2RlJywgKCkgPT4ge1xuICAgIGl0KCdjYWxscyBvbkNoYW5nZSB3aGVuIHJ1YnJpY2xlc3MgaW5zdHJ1Y3Rpb24gaXMgY2hhbmdlZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHsgb25DaGFuZ2UgfSA9IHJlbmRlckNvbXBvbmVudCh7IHJ1YnJpY2xlc3NJbnN0cnVjdGlvbjogJycgfSwgeyBydWJyaWNsZXNzOiB0cnVlIH0pO1xuXG4gICAgICBjb25zdCBjb21wb25lbnQgPSBuZXcgUmF3QXV0aG9yaW5nKHtcbiAgICAgICAgdmFsdWU6IHsgZXhjbHVkZVplcm86IGZhbHNlLCBwb2ludHMsIHNhbXBsZUFuc3dlcnMsIHJ1YnJpY2xlc3NJbnN0cnVjdGlvbjogJycgfSxcbiAgICAgICAgb25DaGFuZ2UsXG4gICAgICAgIGNsYXNzZXM6IHt9LFxuICAgICAgICBjbGFzc05hbWU6ICdjbGFzc05hbWUnLFxuICAgICAgICBydWJyaWNsZXNzOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbXBvbmVudC5jaGFuZ2VSdWJyaWNsZXNzSW5zdHJ1Y3Rpb24oJ05ldyBpbnN0cnVjdGlvbicpO1xuXG4gICAgICBleHBlY3Qob25DaGFuZ2UpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICBleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7XG4gICAgICAgICAgcnVicmljbGVzc0luc3RydWN0aW9uOiAnTmV3IGluc3RydWN0aW9uJyxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZWRnZSBjYXNlcycsICgpID0+IHtcbiAgICBpdCgnaGFuZGxlcyBlbXB0eSBwb2ludHMgYXJyYXknLCAoKSA9PiB7XG4gICAgICBjb25zdCB7IGNvbnRhaW5lciB9ID0gcmVuZGVyQ29tcG9uZW50KHsgcG9pbnRzOiBbXSwgc2FtcGxlQW5zd2VyczogW10gfSk7XG4gICAgICBleHBlY3QoY29udGFpbmVyKS50b0JlSW5UaGVEb2N1bWVudCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2hhbmRsZXMgbWF4UG9pbnRzIGdyZWF0ZXIgdGhhbiBjdXJyZW50IG1heCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHsgb25DaGFuZ2UgfSA9IHJlbmRlckNvbXBvbmVudCgpO1xuXG4gICAgICBjb25zdCBjb21wb25lbnQgPSBuZXcgUmF3QXV0aG9yaW5nKHtcbiAgICAgICAgdmFsdWU6IHsgZXhjbHVkZVplcm86IGZhbHNlLCBwb2ludHMsIHNhbXBsZUFuc3dlcnMgfSxcbiAgICAgICAgb25DaGFuZ2UsXG4gICAgICAgIGNsYXNzZXM6IHt9LFxuICAgICAgICBjbGFzc05hbWU6ICdjbGFzc05hbWUnLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbXBvbmVudC5jaGFuZ2VNYXhQb2ludHMoMTApO1xuXG4gICAgICBleHBlY3Qob25DaGFuZ2UpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IG9uQ2hhbmdlLm1vY2suY2FsbHNbMF1bMF07XG4gICAgICBleHBlY3QocmVzdWx0LnBvaW50cy5sZW5ndGgpLnRvQmUoMTEpOyAvLyAxMCArIDEgZm9yIDAgcG9pbnRzXG4gICAgfSk7XG5cbiAgICBpdCgnaGFuZGxlcyBjb25maWcgYW5kIHBsdWdpbk9wdHMgcHJvcHMnLCAoKSA9PiB7XG4gICAgICBjb25zdCBjb25maWcgPSB7IHNvbWVDb25maWc6IHRydWUgfTtcbiAgICAgIGNvbnN0IHBsdWdpbk9wdHMgPSB7IHNvbWVQbHVnaW46IHRydWUgfTtcbiAgICAgIGNvbnN0IHsgY29udGFpbmVyIH0gPSByZW5kZXJDb21wb25lbnQoe30sIHsgY29uZmlnLCBwbHVnaW5PcHRzIH0pO1xuICAgICAgZXhwZWN0KGNvbnRhaW5lcikudG9CZUluVGhlRG9jdW1lbnQoKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLElBQUFBLE1BQUEsR0FBQUMsT0FBQTtBQUNBLElBQUFDLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFHLFVBQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLFNBQUEsR0FBQUosT0FBQTtBQUNBLElBQUFLLE9BQUEsR0FBQUwsT0FBQTtBQUFrRSxTQUFBTSxRQUFBQyxDQUFBLEVBQUFDLENBQUEsUUFBQUMsQ0FBQSxHQUFB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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-lib/rubric",
|
|
3
|
-
"version": "2.0.22-beta.
|
|
3
|
+
"version": "2.0.22-beta.7",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"@hello-pangea/dnd": "^18.0.1",
|
|
14
14
|
"@mui/icons-material": "^7.3.4",
|
|
15
15
|
"@mui/material": "^7.3.4",
|
|
16
|
-
"@pie-lib/editable-html-tip-tap": "^2.1.20-beta.
|
|
16
|
+
"@pie-lib/editable-html-tip-tap": "^2.1.20-beta.7",
|
|
17
17
|
"debug": "^4.1.1",
|
|
18
18
|
"lodash-es": "^4.17.23",
|
|
19
19
|
"prop-types": "^15.7.2",
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { RawAuthoring } from '../authoring';
|
|
4
|
+
import { takeRight } from 'lodash-es';
|
|
5
|
+
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
|
6
|
+
|
|
7
|
+
// Mock dependencies
|
|
8
|
+
jest.mock('@pie-lib/editable-html-tip-tap', () => {
|
|
9
|
+
return function EditableHtml(props) {
|
|
10
|
+
return <div data-testid="editable-html" data-markup={props.markup} />;
|
|
11
|
+
};
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
jest.mock('@pie-lib/config-ui', () => ({
|
|
15
|
+
FeedbackConfig: ({ feedback }) => <div data-testid="feedback-config">{JSON.stringify(feedback)}</div>,
|
|
16
|
+
InputContainer: ({ children, label }) => (
|
|
17
|
+
<div data-testid="input-container" data-label={label}>
|
|
18
|
+
{children}
|
|
19
|
+
</div>
|
|
20
|
+
),
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
jest.mock('@hello-pangea/dnd', () => ({
|
|
24
|
+
DragDropContext: ({ children }) => <div data-testid="drag-drop-context">{children}</div>,
|
|
25
|
+
Droppable: ({ children }) => children({ droppableProps: {}, innerRef: () => {} }, {}),
|
|
26
|
+
Draggable: ({ children, index }) =>
|
|
27
|
+
children(
|
|
28
|
+
{
|
|
29
|
+
innerRef: () => {},
|
|
30
|
+
draggableProps: { 'data-draggable-index': index },
|
|
31
|
+
dragHandleProps: {},
|
|
32
|
+
},
|
|
33
|
+
{},
|
|
34
|
+
),
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
describe('Rubric', () => {
|
|
38
|
+
const points = ['nothing right', 'a teeny bit right', 'mostly right', 'bingo'];
|
|
39
|
+
const sampleAnswers = [null, 'just right', 'not left', null];
|
|
40
|
+
const theme = createTheme();
|
|
41
|
+
|
|
42
|
+
const renderComponent = (value = {}, props = {}) => {
|
|
43
|
+
const defaultProps = {
|
|
44
|
+
classes: {},
|
|
45
|
+
onChange: jest.fn(),
|
|
46
|
+
className: 'className',
|
|
47
|
+
value: {
|
|
48
|
+
excludeZero: false,
|
|
49
|
+
points,
|
|
50
|
+
sampleAnswers,
|
|
51
|
+
...value,
|
|
52
|
+
},
|
|
53
|
+
...props,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
...render(
|
|
58
|
+
<ThemeProvider theme={theme}>
|
|
59
|
+
<RawAuthoring {...defaultProps} />
|
|
60
|
+
</ThemeProvider>,
|
|
61
|
+
),
|
|
62
|
+
onChange: defaultProps.onChange,
|
|
63
|
+
props: defaultProps,
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
describe('render', () => {
|
|
68
|
+
it('renders rubric title and main structure', () => {
|
|
69
|
+
renderComponent();
|
|
70
|
+
expect(screen.getByText('Rubric')).toBeInTheDocument();
|
|
71
|
+
expect(screen.getByLabelText('Max Points')).toBeInTheDocument();
|
|
72
|
+
expect(screen.getByLabelText('Exclude zeros')).toBeInTheDocument();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('renders all point configurations', () => {
|
|
76
|
+
const { container } = renderComponent();
|
|
77
|
+
// Verify DragDropContext is rendered
|
|
78
|
+
expect(container.querySelector('[data-testid="drag-drop-context"]')).toBeInTheDocument();
|
|
79
|
+
|
|
80
|
+
// Check that point labels are rendered (4 points = "3 pts", "2 pts", "1 pt", "0 pt")
|
|
81
|
+
// Note: The PointConfig component uses singular "pt" for 0 and 1, plural "pts" for 2+
|
|
82
|
+
expect(screen.getByText('3 pts')).toBeInTheDocument();
|
|
83
|
+
expect(screen.getByText('2 pts')).toBeInTheDocument();
|
|
84
|
+
expect(screen.getByText('1 pt')).toBeInTheDocument();
|
|
85
|
+
expect(screen.getByText('0 pt')).toBeInTheDocument();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('draggable', () => {
|
|
89
|
+
it('renders 3 draggable items when excludeZero is true', () => {
|
|
90
|
+
// When excludeZero is true, the last point (0 pts) should not be rendered
|
|
91
|
+
expect(screen.queryByText('0 pt')).not.toBeInTheDocument();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('renders 4 draggable items when excludeZero is false', () => {
|
|
95
|
+
const { container } = renderComponent({ excludeZero: false });
|
|
96
|
+
|
|
97
|
+
// When excludeZero is false, all points including 0 should be rendered
|
|
98
|
+
const draggableItems = container.querySelectorAll('[data-draggable-index]');
|
|
99
|
+
expect(draggableItems.length).toEqual(4);
|
|
100
|
+
expect(screen.getByText('0 pt')).toBeInTheDocument();
|
|
101
|
+
|
|
102
|
+
// Verify all point labels are rendered
|
|
103
|
+
expect(screen.getByText('3 pts')).toBeInTheDocument();
|
|
104
|
+
expect(screen.getByText('2 pts')).toBeInTheDocument();
|
|
105
|
+
expect(screen.getByText('1 pt')).toBeInTheDocument();
|
|
106
|
+
expect(screen.getByText('0 pt')).toBeInTheDocument();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('logic', () => {
|
|
112
|
+
describe('changeMaxPoints', () => {
|
|
113
|
+
const testChangeMaxPoints = (maxPoints, excludeZero, expectedPoints, expectedSampleAnswers) => {
|
|
114
|
+
it(`maxPoints=${maxPoints}, excludeZero=${excludeZero} calls onChange correctly`, () => {
|
|
115
|
+
const { onChange, container } = renderComponent({ excludeZero });
|
|
116
|
+
|
|
117
|
+
// Get the component instance through the container
|
|
118
|
+
// We need to call the method directly since we're testing internal behavior
|
|
119
|
+
const instance = container.querySelector('[class*="MuiBox-root"]')?._owner;
|
|
120
|
+
|
|
121
|
+
// Since we can't easily access instance methods in RTL, we'll test the behavior
|
|
122
|
+
// by verifying the onChange prop receives the correct values
|
|
123
|
+
// For now, we'll directly test the logic
|
|
124
|
+
const component = new RawAuthoring({
|
|
125
|
+
value: { excludeZero, points, sampleAnswers },
|
|
126
|
+
onChange,
|
|
127
|
+
classes: {},
|
|
128
|
+
className: 'className',
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
component.changeMaxPoints(maxPoints);
|
|
132
|
+
|
|
133
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
134
|
+
excludeZero,
|
|
135
|
+
points: expectedPoints,
|
|
136
|
+
sampleAnswers: expectedSampleAnswers,
|
|
137
|
+
maxPoints: expectedPoints.length - 1,
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
testChangeMaxPoints(1, false, takeRight(points, 2), takeRight(sampleAnswers, 2));
|
|
143
|
+
testChangeMaxPoints(1, true, takeRight(points, 2), takeRight(sampleAnswers, 2));
|
|
144
|
+
testChangeMaxPoints(2, true, takeRight(points, 3), takeRight(sampleAnswers, 3));
|
|
145
|
+
testChangeMaxPoints(2, false, takeRight(points, 3), takeRight(sampleAnswers, 3));
|
|
146
|
+
testChangeMaxPoints(5, false, ['', ''].concat(points), [null, null].concat(sampleAnswers));
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe('changeSampleResponse', () => {
|
|
150
|
+
const testChangeSampleResponse = (index, clickedItem, excludeZero, expectedPoints, expectedSampleAnswers) => {
|
|
151
|
+
it(`Point ${index} with clickedItem="${clickedItem}" calls onChange correctly`, () => {
|
|
152
|
+
const { onChange } = renderComponent({ excludeZero });
|
|
153
|
+
|
|
154
|
+
// Test the logic by creating a component instance and calling the method
|
|
155
|
+
const component = new RawAuthoring({
|
|
156
|
+
value: { excludeZero, points, sampleAnswers },
|
|
157
|
+
onChange,
|
|
158
|
+
classes: {},
|
|
159
|
+
className: 'className',
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
component.onPointMenuChange(index, clickedItem);
|
|
163
|
+
|
|
164
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
165
|
+
excludeZero,
|
|
166
|
+
points: expectedPoints,
|
|
167
|
+
sampleAnswers: expectedSampleAnswers,
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
testChangeSampleResponse(0, 'sample', false, points, ['', 'just right', 'not left', null]);
|
|
173
|
+
testChangeSampleResponse(3, 'sample', false, points, [null, 'just right', 'not left', '']);
|
|
174
|
+
testChangeSampleResponse(1, 'sample', true, points, [null, null, 'not left', null]);
|
|
175
|
+
testChangeSampleResponse(3, 'sample', true, points, [null, 'just right', 'not left', '']);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe('user interactions', () => {
|
|
180
|
+
it('calls onChange when excluding zeros checkbox is toggled', () => {
|
|
181
|
+
const { onChange } = renderComponent({ excludeZero: false });
|
|
182
|
+
|
|
183
|
+
const checkbox = screen.getByLabelText('Exclude zeros');
|
|
184
|
+
fireEvent.click(checkbox);
|
|
185
|
+
|
|
186
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
187
|
+
expect.objectContaining({
|
|
188
|
+
excludeZero: true,
|
|
189
|
+
}),
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('calls onChange when max points is changed', () => {
|
|
194
|
+
const { onChange } = renderComponent();
|
|
195
|
+
|
|
196
|
+
const selectInput = screen.getByLabelText('Max Points');
|
|
197
|
+
fireEvent.mouseDown(selectInput);
|
|
198
|
+
|
|
199
|
+
// The onChange should be called when a new value is selected
|
|
200
|
+
// This tests the changeMaxPoints logic indirectly
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('renders correct number of points based on excludeZero', () => {
|
|
204
|
+
const { rerender } = renderComponent({ excludeZero: false });
|
|
205
|
+
expect(screen.getByText('0 pt')).toBeInTheDocument();
|
|
206
|
+
|
|
207
|
+
// Rerender with excludeZero true
|
|
208
|
+
rerender(
|
|
209
|
+
<ThemeProvider theme={theme}>
|
|
210
|
+
<RawAuthoring
|
|
211
|
+
classes={{}}
|
|
212
|
+
onChange={jest.fn()}
|
|
213
|
+
className="className"
|
|
214
|
+
value={{ excludeZero: true, points, sampleAnswers }}
|
|
215
|
+
/>
|
|
216
|
+
</ThemeProvider>,
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
expect(screen.queryByText('0 pt')).not.toBeInTheDocument();
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
describe('drag and drop', () => {
|
|
224
|
+
it('calls onChange with reordered points after drag end', () => {
|
|
225
|
+
const { onChange } = renderComponent();
|
|
226
|
+
|
|
227
|
+
const component = new RawAuthoring({
|
|
228
|
+
value: { excludeZero: false, points, sampleAnswers },
|
|
229
|
+
onChange,
|
|
230
|
+
classes: {},
|
|
231
|
+
className: 'className',
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// Simulate drag from index 0 to index 2
|
|
235
|
+
component.dragEnd({
|
|
236
|
+
source: { index: 0 },
|
|
237
|
+
destination: { index: 2 },
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
expect(onChange).toHaveBeenCalled();
|
|
241
|
+
const result = onChange.mock.calls[0][0];
|
|
242
|
+
expect(result.points).not.toEqual(points);
|
|
243
|
+
expect(result.points.length).toBe(points.length);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('does nothing when drag has no destination', () => {
|
|
247
|
+
const { onChange } = renderComponent();
|
|
248
|
+
|
|
249
|
+
const component = new RawAuthoring({
|
|
250
|
+
value: { excludeZero: false, points, sampleAnswers },
|
|
251
|
+
onChange,
|
|
252
|
+
classes: {},
|
|
253
|
+
className: 'className',
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// Simulate drag without destination
|
|
257
|
+
component.dragEnd({
|
|
258
|
+
source: { index: 0 },
|
|
259
|
+
destination: null,
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
describe('content editing', () => {
|
|
267
|
+
it('calls onChange when point content is changed', () => {
|
|
268
|
+
const { onChange } = renderComponent();
|
|
269
|
+
|
|
270
|
+
const component = new RawAuthoring({
|
|
271
|
+
value: { excludeZero: false, points, sampleAnswers },
|
|
272
|
+
onChange,
|
|
273
|
+
classes: {},
|
|
274
|
+
className: 'className',
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
component.changeContent(0, 'new content', 'points');
|
|
278
|
+
|
|
279
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
280
|
+
expect.objectContaining({
|
|
281
|
+
points: expect.arrayContaining(['new content']),
|
|
282
|
+
}),
|
|
283
|
+
);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('calls onChange when sample answer is changed', () => {
|
|
287
|
+
const { onChange } = renderComponent();
|
|
288
|
+
|
|
289
|
+
const component = new RawAuthoring({
|
|
290
|
+
value: { excludeZero: false, points, sampleAnswers },
|
|
291
|
+
onChange,
|
|
292
|
+
classes: {},
|
|
293
|
+
className: 'className',
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
component.changeContent(1, 'new sample answer', 'sampleAnswers');
|
|
297
|
+
|
|
298
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
299
|
+
expect.objectContaining({
|
|
300
|
+
sampleAnswers: expect.arrayContaining(['new sample answer']),
|
|
301
|
+
}),
|
|
302
|
+
);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('does not change content for invalid type', () => {
|
|
306
|
+
const { onChange } = renderComponent();
|
|
307
|
+
|
|
308
|
+
const component = new RawAuthoring({
|
|
309
|
+
value: { excludeZero: false, points, sampleAnswers },
|
|
310
|
+
onChange,
|
|
311
|
+
classes: {},
|
|
312
|
+
className: 'className',
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
component.changeContent(0, 'new content', 'invalidType');
|
|
316
|
+
|
|
317
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
describe('rubricless mode', () => {
|
|
322
|
+
it('calls onChange when rubricless instruction is changed', () => {
|
|
323
|
+
const { onChange } = renderComponent({ rubriclessInstruction: '' }, { rubricless: true });
|
|
324
|
+
|
|
325
|
+
const component = new RawAuthoring({
|
|
326
|
+
value: { excludeZero: false, points, sampleAnswers, rubriclessInstruction: '' },
|
|
327
|
+
onChange,
|
|
328
|
+
classes: {},
|
|
329
|
+
className: 'className',
|
|
330
|
+
rubricless: true,
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
component.changeRubriclessInstruction('New instruction');
|
|
334
|
+
|
|
335
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
336
|
+
expect.objectContaining({
|
|
337
|
+
rubriclessInstruction: 'New instruction',
|
|
338
|
+
}),
|
|
339
|
+
);
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
describe('edge cases', () => {
|
|
344
|
+
it('handles empty points array', () => {
|
|
345
|
+
const { container } = renderComponent({ points: [], sampleAnswers: [] });
|
|
346
|
+
expect(container).toBeInTheDocument();
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it('handles maxPoints greater than current max', () => {
|
|
350
|
+
const { onChange } = renderComponent();
|
|
351
|
+
|
|
352
|
+
const component = new RawAuthoring({
|
|
353
|
+
value: { excludeZero: false, points, sampleAnswers },
|
|
354
|
+
onChange,
|
|
355
|
+
classes: {},
|
|
356
|
+
className: 'className',
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
component.changeMaxPoints(10);
|
|
360
|
+
|
|
361
|
+
expect(onChange).toHaveBeenCalled();
|
|
362
|
+
const result = onChange.mock.calls[0][0];
|
|
363
|
+
expect(result.points.length).toBe(11); // 10 + 1 for 0 points
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
it('handles config and pluginOpts props', () => {
|
|
367
|
+
const config = { someConfig: true };
|
|
368
|
+
const pluginOpts = { somePlugin: true };
|
|
369
|
+
const { container } = renderComponent({}, { config, pluginOpts });
|
|
370
|
+
expect(container).toBeInTheDocument();
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
});
|