@pie-lib/math-toolbar 3.1.0-beta.3 → 3.1.0-beta.5

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.
@@ -0,0 +1,272 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
5
+ var _editorAndPad = require("../editor-and-pad");
6
+ 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; }
7
+ 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; }
8
+ /**
9
+ * Covers the call sites that changed when this package moved from
10
+ * @pie-lib/math-input (MathQuill) to @pie-lib/math-input-mathlive.
11
+ *
12
+ * All three were MathQuill-shaped and silently changed meaning:
13
+ * - shouldComponentUpdate read `this.input.mathField.latex()`, which throws now
14
+ * (and the field loads asynchronously, so `this.input` can be null)
15
+ * - the mixed-number workaround poked `__controller.cursor`, a MathQuill
16
+ * internal with no MathLive equivalent
17
+ * - onClick routes keypad presses through the imperative field API
18
+ */
19
+ describe('EditorAndPad after the MathLive migration', function () {
20
+ var props = function props() {
21
+ var over = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
22
+ return _objectSpread({
23
+ classes: {},
24
+ classNames: {},
25
+ onChange: jest.fn()
26
+ }, over);
27
+ };
28
+ describe('shouldComponentUpdate', function () {
29
+ it('treats a missing input ref as different, so the first render is not skipped', function () {
30
+ var c = new _editorAndPad.EditorAndPad(props({
31
+ latex: 'x'
32
+ }));
33
+ c.input = null;
34
+ expect(c.shouldComponentUpdate({
35
+ latex: 'x'
36
+ }, {})).toBe(true);
37
+ });
38
+ it('does not throw when the math engine has not loaded yet', function () {
39
+ var c = new _editorAndPad.EditorAndPad(props({
40
+ latex: 'x'
41
+ }));
42
+
43
+ // latex() returns '' until MathLive is ready
44
+ c.input = {
45
+ latex: function latex() {
46
+ return '';
47
+ }
48
+ };
49
+ expect(function () {
50
+ return c.shouldComponentUpdate({
51
+ latex: 'x'
52
+ }, {});
53
+ }).not.toThrow();
54
+ expect(c.shouldComponentUpdate({
55
+ latex: 'x'
56
+ }, {})).toBe(true);
57
+ });
58
+ it('skips the update when the field already holds the incoming latex', function () {
59
+ var c = new _editorAndPad.EditorAndPad(props({
60
+ latex: 'x',
61
+ keypadMode: 'a',
62
+ noDecimal: false
63
+ }));
64
+ c.input = {
65
+ latex: function latex() {
66
+ return 'x';
67
+ }
68
+ };
69
+ c.state = {
70
+ equationEditor: 'geometry'
71
+ };
72
+ expect(c.shouldComponentUpdate({
73
+ latex: 'x',
74
+ keypadMode: 'a',
75
+ noDecimal: false
76
+ }, c.state)).toBe(false);
77
+ });
78
+ it('re-renders when the field differs from the incoming latex', function () {
79
+ var c = new _editorAndPad.EditorAndPad(props({
80
+ latex: 'y'
81
+ }));
82
+ c.input = {
83
+ latex: function latex() {
84
+ return 'x';
85
+ }
86
+ };
87
+ expect(c.shouldComponentUpdate({
88
+ latex: 'y'
89
+ }, {})).toBe(true);
90
+ });
91
+ it('uses input.latex(), never input.mathField.latex()', function () {
92
+ var c = new _editorAndPad.EditorAndPad(props({
93
+ latex: 'x'
94
+ }));
95
+ var latex = jest.fn(function () {
96
+ return 'x';
97
+ });
98
+
99
+ // deliberately no `mathField` - the old code would have thrown here
100
+ c.input = {
101
+ latex: latex
102
+ };
103
+ c.state = {
104
+ equationEditor: 'geometry'
105
+ };
106
+ c.shouldComponentUpdate({
107
+ latex: 'x'
108
+ }, c.state);
109
+ expect(latex).toHaveBeenCalled();
110
+ });
111
+ });
112
+ describe('onClick key routing', function () {
113
+ var withInput = function withInput() {
114
+ var over = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
115
+ var c = new _editorAndPad.EditorAndPad(props(over));
116
+ var calls = {
117
+ write: [],
118
+ command: [],
119
+ keystroke: [],
120
+ clear: 0
121
+ };
122
+ c.input = {
123
+ write: function write(v) {
124
+ return calls.write.push(v);
125
+ },
126
+ command: function command(v) {
127
+ return calls.command.push(v);
128
+ },
129
+ keystroke: function keystroke(v) {
130
+ return calls.keystroke.push(v);
131
+ },
132
+ clear: function clear() {
133
+ return calls.clear++;
134
+ }
135
+ };
136
+ c.updateDisable = function () {};
137
+ return {
138
+ c: c,
139
+ calls: calls
140
+ };
141
+ };
142
+
143
+ // toNodeData keys this off `value === 'clear'`, not `type`
144
+ it('clear', function () {
145
+ var _withInput = withInput(),
146
+ c = _withInput.c,
147
+ calls = _withInput.calls;
148
+ c.onClick({
149
+ value: 'clear'
150
+ });
151
+ expect(calls.clear).toBe(1);
152
+ });
153
+ it('command', function () {
154
+ var _withInput2 = withInput(),
155
+ c = _withInput2.c,
156
+ calls = _withInput2.calls;
157
+ c.onClick({
158
+ type: 'command',
159
+ value: '\\frac'
160
+ });
161
+ expect(calls.command).toEqual(['\\frac']);
162
+ });
163
+ it('cursor keystroke', function () {
164
+ var _withInput3 = withInput(),
165
+ c = _withInput3.c,
166
+ calls = _withInput3.calls;
167
+ c.onClick({
168
+ type: 'cursor',
169
+ value: 'Left'
170
+ });
171
+ expect(calls.keystroke).toEqual(['Left']);
172
+ });
173
+ it('answer block writes the response token', function () {
174
+ var _withInput4 = withInput(),
175
+ c = _withInput4.c,
176
+ calls = _withInput4.calls;
177
+ c.onClick({
178
+ type: 'answer'
179
+ });
180
+ expect(calls.write).toEqual(['%response%']);
181
+ });
182
+ it('plain value', function () {
183
+ var _withInput5 = withInput(),
184
+ c = _withInput5.c,
185
+ calls = _withInput5.calls;
186
+ c.onClick({
187
+ value: 'x'
188
+ });
189
+ expect(calls.write).toEqual(['x']);
190
+ });
191
+ it('ignores a nullish key', function () {
192
+ var _withInput6 = withInput(),
193
+ c = _withInput6.c,
194
+ calls = _withInput6.calls;
195
+ expect(function () {
196
+ return c.onClick(null);
197
+ }).not.toThrow();
198
+ expect(calls.write).toEqual([]);
199
+ });
200
+ });
201
+ describe('onEditorChange', function () {
202
+ var withInput = function withInput() {
203
+ var over = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
204
+ var onChange = jest.fn();
205
+ var c = new _editorAndPad.EditorAndPad(props(_objectSpread({
206
+ onChange: onChange
207
+ }, over)));
208
+ var calls = {
209
+ keystroke: [],
210
+ clear: 0,
211
+ write: []
212
+ };
213
+ c.input = {
214
+ keystroke: function keystroke(v) {
215
+ return calls.keystroke.push(v);
216
+ },
217
+ clear: function clear() {
218
+ return calls.clear++;
219
+ },
220
+ write: function write(v) {
221
+ return calls.write.push(v);
222
+ }
223
+ };
224
+ c.updateDisable = function () {};
225
+ return {
226
+ c: c,
227
+ onChange: onChange,
228
+ calls: calls
229
+ };
230
+ };
231
+ it('propagates ordinary latex to onChange', function () {
232
+ var _withInput7 = withInput(),
233
+ c = _withInput7.c,
234
+ onChange = _withInput7.onChange;
235
+ c.onEditorChange('\\frac{1}{2}');
236
+ expect(onChange).toHaveBeenCalledWith('\\frac{1}{2}');
237
+ });
238
+ it('strips decimals when noDecimal is set', function () {
239
+ var _withInput8 = withInput({
240
+ noDecimal: true
241
+ }),
242
+ c = _withInput8.c,
243
+ onChange = _withInput8.onChange,
244
+ calls = _withInput8.calls;
245
+ c.onEditorChange('1.5');
246
+ expect(calls.clear).toBe(1);
247
+ expect(calls.write).toEqual(['15']);
248
+ expect(onChange).not.toHaveBeenCalled();
249
+ });
250
+ it('undoes the empty fraction after a digit with a public delete, not MathQuill internals', function () {
251
+ var _withInput9 = withInput(),
252
+ c = _withInput9.c,
253
+ onChange = _withInput9.onChange,
254
+ calls = _withInput9.calls;
255
+
256
+ // the shape the old __controller hack targeted
257
+ c.onEditorChange('2\\ \\frac{1}{ }');
258
+ expect(calls.keystroke).toEqual(['Backspace']);
259
+ expect(onChange).not.toHaveBeenCalled();
260
+ });
261
+ it('does not treat normal fractions as the mixed-number case', function () {
262
+ var _withInput0 = withInput(),
263
+ c = _withInput0.c,
264
+ onChange = _withInput0.onChange,
265
+ calls = _withInput0.calls;
266
+ c.onEditorChange('\\frac{1}{2}');
267
+ expect(calls.keystroke).toEqual([]);
268
+ expect(onChange).toHaveBeenCalled();
269
+ });
270
+ });
271
+ });
272
+ //# sourceMappingURL=editor-and-pad-mathlive.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-and-pad-mathlive.test.js","names":["_editorAndPad","require","ownKeys","e","r","t","Object","keys","getOwnPropertySymbols","o","filter","getOwnPropertyDescriptor","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty2","getOwnPropertyDescriptors","defineProperties","defineProperty","describe","props","over","undefined","classes","classNames","onChange","jest","fn","it","c","EditorAndPad","latex","input","expect","shouldComponentUpdate","toBe","not","toThrow","keypadMode","noDecimal","state","equationEditor","toHaveBeenCalled","withInput","calls","write","command","keystroke","clear","v","updateDisable","_withInput","onClick","value","_withInput2","type","toEqual","_withInput3","_withInput4","_withInput5","_withInput6","_withInput7","onEditorChange","toHaveBeenCalledWith","_withInput8","_withInput9","_withInput0"],"sources":["../../src/__tests__/editor-and-pad-mathlive.test.js"],"sourcesContent":["import { EditorAndPad } from '../editor-and-pad';\n\n/**\n * Covers the call sites that changed when this package moved from\n * @pie-lib/math-input (MathQuill) to @pie-lib/math-input-mathlive.\n *\n * All three were MathQuill-shaped and silently changed meaning:\n * - shouldComponentUpdate read `this.input.mathField.latex()`, which throws now\n * (and the field loads asynchronously, so `this.input` can be null)\n * - the mixed-number workaround poked `__controller.cursor`, a MathQuill\n * internal with no MathLive equivalent\n * - onClick routes keypad presses through the imperative field API\n */\ndescribe('EditorAndPad after the MathLive migration', () => {\n const props = (over = {}) => ({ classes: {}, classNames: {}, onChange: jest.fn(), ...over });\n\n describe('shouldComponentUpdate', () => {\n it('treats a missing input ref as different, so the first render is not skipped', () => {\n const c = new EditorAndPad(props({ latex: 'x' }));\n\n c.input = null;\n\n expect(c.shouldComponentUpdate({ latex: 'x' }, {})).toBe(true);\n });\n\n it('does not throw when the math engine has not loaded yet', () => {\n const c = new EditorAndPad(props({ latex: 'x' }));\n\n // latex() returns '' until MathLive is ready\n c.input = { latex: () => '' };\n\n expect(() => c.shouldComponentUpdate({ latex: 'x' }, {})).not.toThrow();\n expect(c.shouldComponentUpdate({ latex: 'x' }, {})).toBe(true);\n });\n\n it('skips the update when the field already holds the incoming latex', () => {\n const c = new EditorAndPad(props({ latex: 'x', keypadMode: 'a', noDecimal: false }));\n\n c.input = { latex: () => 'x' };\n c.state = { equationEditor: 'geometry' };\n\n expect(c.shouldComponentUpdate({ latex: 'x', keypadMode: 'a', noDecimal: false }, c.state)).toBe(false);\n });\n\n it('re-renders when the field differs from the incoming latex', () => {\n const c = new EditorAndPad(props({ latex: 'y' }));\n\n c.input = { latex: () => 'x' };\n\n expect(c.shouldComponentUpdate({ latex: 'y' }, {})).toBe(true);\n });\n\n it('uses input.latex(), never input.mathField.latex()', () => {\n const c = new EditorAndPad(props({ latex: 'x' }));\n const latex = jest.fn(() => 'x');\n\n // deliberately no `mathField` - the old code would have thrown here\n c.input = { latex };\n c.state = { equationEditor: 'geometry' };\n c.shouldComponentUpdate({ latex: 'x' }, c.state);\n\n expect(latex).toHaveBeenCalled();\n });\n });\n\n describe('onClick key routing', () => {\n const withInput = (over = {}) => {\n const c = new EditorAndPad(props(over));\n const calls = { write: [], command: [], keystroke: [], clear: 0 };\n\n c.input = {\n write: (v) => calls.write.push(v),\n command: (v) => calls.command.push(v),\n keystroke: (v) => calls.keystroke.push(v),\n clear: () => calls.clear++,\n };\n c.updateDisable = () => {};\n\n return { c, calls };\n };\n\n // toNodeData keys this off `value === 'clear'`, not `type`\n it('clear', () => {\n const { c, calls } = withInput();\n\n c.onClick({ value: 'clear' });\n expect(calls.clear).toBe(1);\n });\n\n it('command', () => {\n const { c, calls } = withInput();\n\n c.onClick({ type: 'command', value: '\\\\frac' });\n expect(calls.command).toEqual(['\\\\frac']);\n });\n\n it('cursor keystroke', () => {\n const { c, calls } = withInput();\n\n c.onClick({ type: 'cursor', value: 'Left' });\n expect(calls.keystroke).toEqual(['Left']);\n });\n\n it('answer block writes the response token', () => {\n const { c, calls } = withInput();\n\n c.onClick({ type: 'answer' });\n expect(calls.write).toEqual(['%response%']);\n });\n\n it('plain value', () => {\n const { c, calls } = withInput();\n\n c.onClick({ value: 'x' });\n expect(calls.write).toEqual(['x']);\n });\n\n it('ignores a nullish key', () => {\n const { c, calls } = withInput();\n\n expect(() => c.onClick(null)).not.toThrow();\n expect(calls.write).toEqual([]);\n });\n });\n\n describe('onEditorChange', () => {\n const withInput = (over = {}) => {\n const onChange = jest.fn();\n const c = new EditorAndPad(props({ onChange, ...over }));\n const calls = { keystroke: [], clear: 0, write: [] };\n\n c.input = {\n keystroke: (v) => calls.keystroke.push(v),\n clear: () => calls.clear++,\n write: (v) => calls.write.push(v),\n };\n c.updateDisable = () => {};\n\n return { c, onChange, calls };\n };\n\n it('propagates ordinary latex to onChange', () => {\n const { c, onChange } = withInput();\n\n c.onEditorChange('\\\\frac{1}{2}');\n expect(onChange).toHaveBeenCalledWith('\\\\frac{1}{2}');\n });\n\n it('strips decimals when noDecimal is set', () => {\n const { c, onChange, calls } = withInput({ noDecimal: true });\n\n c.onEditorChange('1.5');\n\n expect(calls.clear).toBe(1);\n expect(calls.write).toEqual(['15']);\n expect(onChange).not.toHaveBeenCalled();\n });\n\n it('undoes the empty fraction after a digit with a public delete, not MathQuill internals', () => {\n const { c, onChange, calls } = withInput();\n\n // the shape the old __controller hack targeted\n c.onEditorChange('2\\\\ \\\\frac{1}{ }');\n\n expect(calls.keystroke).toEqual(['Backspace']);\n expect(onChange).not.toHaveBeenCalled();\n });\n\n it('does not treat normal fractions as the mixed-number case', () => {\n const { c, onChange, calls } = withInput();\n\n c.onEditorChange('\\\\frac{1}{2}');\n\n expect(calls.keystroke).toEqual([]);\n expect(onChange).toHaveBeenCalled();\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "3.1.0-beta.3",
6
+ "version": "3.1.0-beta.5",
7
7
  "description": "Math toolbar for editing math equations",
8
8
  "keywords": [
9
9
  "math",
@@ -21,7 +21,7 @@
21
21
  "@emotion/styled": "^11.14.1",
22
22
  "@mui/icons-material": "^7.3.4",
23
23
  "@mui/material": "^7.3.4",
24
- "@pie-lib/math-input-mathlive": "^1.0.7",
24
+ "@pie-lib/math-input-mathlive": "^1.0.9",
25
25
  "@pie-lib/render-ui": "^6.1.0",
26
26
  "debug": "^4.1.1",
27
27
  "lodash-es": "^4.17.23",
@@ -0,0 +1,178 @@
1
+ import { EditorAndPad } from '../editor-and-pad';
2
+
3
+ /**
4
+ * Covers the call sites that changed when this package moved from
5
+ * @pie-lib/math-input (MathQuill) to @pie-lib/math-input-mathlive.
6
+ *
7
+ * All three were MathQuill-shaped and silently changed meaning:
8
+ * - shouldComponentUpdate read `this.input.mathField.latex()`, which throws now
9
+ * (and the field loads asynchronously, so `this.input` can be null)
10
+ * - the mixed-number workaround poked `__controller.cursor`, a MathQuill
11
+ * internal with no MathLive equivalent
12
+ * - onClick routes keypad presses through the imperative field API
13
+ */
14
+ describe('EditorAndPad after the MathLive migration', () => {
15
+ const props = (over = {}) => ({ classes: {}, classNames: {}, onChange: jest.fn(), ...over });
16
+
17
+ describe('shouldComponentUpdate', () => {
18
+ it('treats a missing input ref as different, so the first render is not skipped', () => {
19
+ const c = new EditorAndPad(props({ latex: 'x' }));
20
+
21
+ c.input = null;
22
+
23
+ expect(c.shouldComponentUpdate({ latex: 'x' }, {})).toBe(true);
24
+ });
25
+
26
+ it('does not throw when the math engine has not loaded yet', () => {
27
+ const c = new EditorAndPad(props({ latex: 'x' }));
28
+
29
+ // latex() returns '' until MathLive is ready
30
+ c.input = { latex: () => '' };
31
+
32
+ expect(() => c.shouldComponentUpdate({ latex: 'x' }, {})).not.toThrow();
33
+ expect(c.shouldComponentUpdate({ latex: 'x' }, {})).toBe(true);
34
+ });
35
+
36
+ it('skips the update when the field already holds the incoming latex', () => {
37
+ const c = new EditorAndPad(props({ latex: 'x', keypadMode: 'a', noDecimal: false }));
38
+
39
+ c.input = { latex: () => 'x' };
40
+ c.state = { equationEditor: 'geometry' };
41
+
42
+ expect(c.shouldComponentUpdate({ latex: 'x', keypadMode: 'a', noDecimal: false }, c.state)).toBe(false);
43
+ });
44
+
45
+ it('re-renders when the field differs from the incoming latex', () => {
46
+ const c = new EditorAndPad(props({ latex: 'y' }));
47
+
48
+ c.input = { latex: () => 'x' };
49
+
50
+ expect(c.shouldComponentUpdate({ latex: 'y' }, {})).toBe(true);
51
+ });
52
+
53
+ it('uses input.latex(), never input.mathField.latex()', () => {
54
+ const c = new EditorAndPad(props({ latex: 'x' }));
55
+ const latex = jest.fn(() => 'x');
56
+
57
+ // deliberately no `mathField` - the old code would have thrown here
58
+ c.input = { latex };
59
+ c.state = { equationEditor: 'geometry' };
60
+ c.shouldComponentUpdate({ latex: 'x' }, c.state);
61
+
62
+ expect(latex).toHaveBeenCalled();
63
+ });
64
+ });
65
+
66
+ describe('onClick key routing', () => {
67
+ const withInput = (over = {}) => {
68
+ const c = new EditorAndPad(props(over));
69
+ const calls = { write: [], command: [], keystroke: [], clear: 0 };
70
+
71
+ c.input = {
72
+ write: (v) => calls.write.push(v),
73
+ command: (v) => calls.command.push(v),
74
+ keystroke: (v) => calls.keystroke.push(v),
75
+ clear: () => calls.clear++,
76
+ };
77
+ c.updateDisable = () => {};
78
+
79
+ return { c, calls };
80
+ };
81
+
82
+ // toNodeData keys this off `value === 'clear'`, not `type`
83
+ it('clear', () => {
84
+ const { c, calls } = withInput();
85
+
86
+ c.onClick({ value: 'clear' });
87
+ expect(calls.clear).toBe(1);
88
+ });
89
+
90
+ it('command', () => {
91
+ const { c, calls } = withInput();
92
+
93
+ c.onClick({ type: 'command', value: '\\frac' });
94
+ expect(calls.command).toEqual(['\\frac']);
95
+ });
96
+
97
+ it('cursor keystroke', () => {
98
+ const { c, calls } = withInput();
99
+
100
+ c.onClick({ type: 'cursor', value: 'Left' });
101
+ expect(calls.keystroke).toEqual(['Left']);
102
+ });
103
+
104
+ it('answer block writes the response token', () => {
105
+ const { c, calls } = withInput();
106
+
107
+ c.onClick({ type: 'answer' });
108
+ expect(calls.write).toEqual(['%response%']);
109
+ });
110
+
111
+ it('plain value', () => {
112
+ const { c, calls } = withInput();
113
+
114
+ c.onClick({ value: 'x' });
115
+ expect(calls.write).toEqual(['x']);
116
+ });
117
+
118
+ it('ignores a nullish key', () => {
119
+ const { c, calls } = withInput();
120
+
121
+ expect(() => c.onClick(null)).not.toThrow();
122
+ expect(calls.write).toEqual([]);
123
+ });
124
+ });
125
+
126
+ describe('onEditorChange', () => {
127
+ const withInput = (over = {}) => {
128
+ const onChange = jest.fn();
129
+ const c = new EditorAndPad(props({ onChange, ...over }));
130
+ const calls = { keystroke: [], clear: 0, write: [] };
131
+
132
+ c.input = {
133
+ keystroke: (v) => calls.keystroke.push(v),
134
+ clear: () => calls.clear++,
135
+ write: (v) => calls.write.push(v),
136
+ };
137
+ c.updateDisable = () => {};
138
+
139
+ return { c, onChange, calls };
140
+ };
141
+
142
+ it('propagates ordinary latex to onChange', () => {
143
+ const { c, onChange } = withInput();
144
+
145
+ c.onEditorChange('\\frac{1}{2}');
146
+ expect(onChange).toHaveBeenCalledWith('\\frac{1}{2}');
147
+ });
148
+
149
+ it('strips decimals when noDecimal is set', () => {
150
+ const { c, onChange, calls } = withInput({ noDecimal: true });
151
+
152
+ c.onEditorChange('1.5');
153
+
154
+ expect(calls.clear).toBe(1);
155
+ expect(calls.write).toEqual(['15']);
156
+ expect(onChange).not.toHaveBeenCalled();
157
+ });
158
+
159
+ it('undoes the empty fraction after a digit with a public delete, not MathQuill internals', () => {
160
+ const { c, onChange, calls } = withInput();
161
+
162
+ // the shape the old __controller hack targeted
163
+ c.onEditorChange('2\\ \\frac{1}{ }');
164
+
165
+ expect(calls.keystroke).toEqual(['Backspace']);
166
+ expect(onChange).not.toHaveBeenCalled();
167
+ });
168
+
169
+ it('does not treat normal fractions as the mixed-number case', () => {
170
+ const { c, onChange, calls } = withInput();
171
+
172
+ c.onEditorChange('\\frac{1}{2}');
173
+
174
+ expect(calls.keystroke).toEqual([]);
175
+ expect(onChange).toHaveBeenCalled();
176
+ });
177
+ });
178
+ });