| suite('typing with auto-replaces', function() { | |
| var mq; | |
| setup(function() { | |
| mq = MQ.MathField($('<span></span>').appendTo('#mock')[0]); | |
| }); | |
| teardown(function() { | |
| $(mq.el()).remove(); | |
| }); | |
| function prayWellFormedPoint(pt) { prayWellFormed(pt.parent, pt[L], pt[R]); } | |
| function assertLatex(latex) { | |
| prayWellFormedPoint(mq.__controller.cursor); | |
| assert.equal(mq.latex(), latex); | |
| } | |
| suite('LiveFraction', function() { | |
| test('full MathQuill', function() { | |
| mq.typedText('1/2').keystroke('Tab').typedText('+sinx/'); | |
| assertLatex('\\frac{1}{2}+\\frac{\\sin x}{ }'); | |
| mq.latex('').typedText('1+/2'); | |
| assertLatex('1+\\frac{2}{ }'); | |
| mq.latex('').typedText('1 2/3'); | |
| assertLatex('1\\ \\frac{2}{3}'); | |
| }); | |
| test('mathquill-basic', function() { | |
| var mq_basic = MQBasic.MathField($('<span></span>').appendTo('#mock')[0]); | |
| mq_basic.typedText('1/2'); | |
| assert.equal(mq_basic.latex(), '\\frac{1}{2}'); | |
| $(mq_basic.el()).remove(); | |
| }); | |
| }); | |
| suite('LatexCommandInput', function() { | |
| test('basic', function() { | |
| mq.typedText('\\sqrt-x'); | |
| assertLatex('\\sqrt{-x}'); | |
| }); | |
| test('they\'re passed their name', function() { | |
| mq.cmd('\\alpha'); | |
| assert.equal(mq.latex(), '\\alpha'); | |
| }); | |
| test('replaces selection', function() { | |
| mq.typedText('49').select().typedText('\\sqrt').keystroke('Enter'); | |
| assertLatex('\\sqrt{49}'); | |
| }); | |
| test('auto-operator names', function() { | |
| mq.typedText('\\sin^2'); | |
| assertLatex('\\sin^2'); | |
| }); | |
| test('nonexistent LaTeX command', function() { | |
| mq.typedText('\\asdf+'); | |
| assertLatex('\\text{asdf}+'); | |
| }); | |
| test('dollar sign', function() { | |
| mq.typedText('$'); | |
| assertLatex('\\$'); | |
| }); | |
| }); | |
| suite('auto-expanding parens', function() { | |
| suite('simple', function() { | |
| test('empty parens ()', function() { | |
| mq.typedText('('); | |
| assertLatex('\\left(\\right)'); | |
| mq.typedText(')'); | |
| assertLatex('\\left(\\right)'); | |
| }); | |
| test('straight typing 1+(2+3)+4', function() { | |
| mq.typedText('1+(2+3)+4'); | |
| assertLatex('1+\\left(2+3\\right)+4'); | |
| }); | |
| test('basic command \\sin(', function () { | |
| mq.typedText('\\sin('); | |
| assertLatex('\\sin\\left(\\right)'); | |
| }); | |
| test('wrapping things in parens 1+(2+3)+4', function() { | |
| mq.typedText('1+2+3+4'); | |
| assertLatex('1+2+3+4'); | |
| mq.keystroke('Left Left').typedText(')'); | |
| assertLatex('\\left(1+2+3\\right)+4'); | |
| mq.keystroke('Left Left Left Left').typedText('('); | |
| assertLatex('1+\\left(2+3\\right)+4'); | |
| }); | |
| test('nested parens 1+(2+(3+4)+5)+6', function() { | |
| mq.typedText('1+(2+(3+4)+5)+6'); | |
| assertLatex('1+\\left(2+\\left(3+4\\right)+5\\right)+6'); | |
| }); | |
| }); | |
| suite('mismatched brackets', function() { | |
| test('empty mismatched brackets (] and [}', function() { | |
| mq.typedText('('); | |
| assertLatex('\\left(\\right)'); | |
| mq.typedText(']'); | |
| assertLatex('\\left(\\right]'); | |
| mq.typedText('['); | |
| assertLatex('\\left(\\right]\\left[\\right]'); | |
| mq.typedText('}'); | |
| assertLatex('\\left(\\right]\\left[\\right\\}'); | |
| }); | |
| test('typing mismatched brackets 1+(2+3]+4', function() { | |
| mq.typedText('1+'); | |
| assertLatex('1+'); | |
| mq.typedText('('); | |
| assertLatex('1+\\left(\\right)'); | |
| mq.typedText('2+3'); | |
| assertLatex('1+\\left(2+3\\right)'); | |
| mq.typedText(']+4'); | |
| assertLatex('1+\\left(2+3\\right]+4'); | |
| }); | |
| test('wrapping things in mismatched brackets 1+(2+3]+4', function() { | |
| mq.typedText('1+2+3+4'); | |
| assertLatex('1+2+3+4'); | |
| mq.keystroke('Left Left').typedText(']'); | |
| assertLatex('\\left[1+2+3\\right]+4'); | |
| mq.keystroke('Left Left Left Left').typedText('('); | |
| assertLatex('1+\\left(2+3\\right]+4'); | |
| }); | |
| test('nested mismatched brackets 1+(2+[3+4)+5]+6', function() { | |
| mq.typedText('1+(2+[3+4)+5]+6'); | |
| assertLatex('1+\\left(2+\\left[3+4\\right)+5\\right]+6'); | |
| }); | |
| suite('restrictMismatchedBrackets', function() { | |
| setup(function() { | |
| mq.config({ restrictMismatchedBrackets: true }); | |
| }); | |
| test('typing (|x|+1) works', function() { | |
| mq.typedText('(|x|+1)'); | |
| assertLatex('\\left(\\left|x\\right|+1\\right)'); | |
| }); | |
| test('typing [x} becomes [{x}]', function() { | |
| mq.typedText('[x}'); | |
| assertLatex('\\left[\\left\\{x\\right\\}\\right]'); | |
| }); | |
| test('normal matching pairs {f(n), [a,b]} work', function() { | |
| mq.typedText('{f(n), [a,b]}'); | |
| assertLatex('\\left\\{f\\left(n\\right),\\ \\left[a,b\\right]\\right\\}'); | |
| }); | |
| test('[a,b) and (a,b] still work', function() { | |
| mq.typedText('[a,b) + (a,b]'); | |
| assertLatex('\\left[a,b\\right)\\ +\\ \\left(a,b\\right]'); | |
| }); | |
| }); | |
| }); | |
| suite('pipes', function() { | |
| test('empty pipes ||', function() { | |
| mq.typedText('|'); | |
| assertLatex('\\left|\\right|'); | |
| mq.typedText('|'); | |
| assertLatex('\\left|\\right|'); | |
| }); | |
| test('straight typing 1+|2+3|+4', function() { | |
| mq.typedText('1+|2+3|+4'); | |
| assertLatex('1+\\left|2+3\\right|+4'); | |
| }); | |
| test('wrapping things in pipes 1+|2+3|+4', function() { | |
| mq.typedText('1+2+3+4'); | |
| assertLatex('1+2+3+4'); | |
| mq.keystroke('Home Right Right').typedText('|'); | |
| assertLatex('1+\\left|2+3+4\\right|'); | |
| mq.keystroke('Right Right Right').typedText('|'); | |
| assertLatex('1+\\left|2+3\\right|+4'); | |
| }); | |
| suite('can type mismatched paren/pipe group from any side', function() { | |
| suite('straight typing', function() { | |
| test('|)', function() { | |
| mq.typedText('|)'); | |
| assertLatex('\\left|\\right)'); | |
| }); | |
| test('(|', function() { | |
| mq.typedText('(|'); | |
| assertLatex('\\left(\\right|'); | |
| }); | |
| }); | |
| suite('the other direction', function() { | |
| test('|)', function() { | |
| mq.typedText(')'); | |
| assertLatex('\\left(\\right)'); | |
| mq.keystroke('Left').typedText('|'); | |
| assertLatex('\\left|\\right)'); | |
| }); | |
| test('(|', function() { | |
| mq.typedText('||'); | |
| assertLatex('\\left|\\right|'); | |
| mq.keystroke('Left Left Del'); | |
| assertLatex('\\left|\\right|'); | |
| mq.typedText('('); | |
| assertLatex('\\left(\\right|'); | |
| }); | |
| }); | |
| }); | |
| }); | |
| suite('backspacing', backspacingTests); | |
| suite('backspacing with restrictMismatchedBrackets', function() { | |
| setup(function() { | |
| mq.config({ restrictMismatchedBrackets: true }); | |
| }); | |
| backspacingTests(); | |
| }); | |
| function backspacingTests() { | |
| test('typing then backspacing a close-paren in the middle of 1+2+3+4', function() { | |
| mq.typedText('1+2+3+4'); | |
| assertLatex('1+2+3+4'); | |
| mq.keystroke('Left Left').typedText(')'); | |
| assertLatex('\\left(1+2+3\\right)+4'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('backspacing close-paren then open-paren of 1+(2+3)+4', function() { | |
| mq.typedText('1+(2+3)+4'); | |
| assertLatex('1+\\left(2+3\\right)+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('1+\\left(2+3+4\\right)'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('backspacing open-paren of 1+(2+3)+4', function() { | |
| mq.typedText('1+(2+3)+4'); | |
| assertLatex('1+\\left(2+3\\right)+4'); | |
| mq.keystroke('Left Left Left Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('backspacing close-bracket then open-paren of 1+(2+3]+4', function() { | |
| mq.typedText('1+(2+3]+4'); | |
| assertLatex('1+\\left(2+3\\right]+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('1+\\left(2+3+4\\right)'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('backspacing open-paren of 1+(2+3]+4', function() { | |
| mq.typedText('1+(2+3]+4'); | |
| assertLatex('1+\\left(2+3\\right]+4'); | |
| mq.keystroke('Left Left Left Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('backspacing close-bracket then open-paren of 1+(2+3] (nothing after paren group)', function() { | |
| mq.typedText('1+(2+3]'); | |
| assertLatex('1+\\left(2+3\\right]'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+\\left(2+3\\right)'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1+2+3'); | |
| }); | |
| test('backspacing open-paren of 1+(2+3] (nothing after paren group)', function() { | |
| mq.typedText('1+(2+3]'); | |
| assertLatex('1+\\left(2+3\\right]'); | |
| mq.keystroke('Left Left Left Left Backspace'); | |
| assertLatex('1+2+3'); | |
| }); | |
| test('backspacing close-bracket then open-paren of (2+3]+4 (nothing before paren group)', function() { | |
| mq.typedText('(2+3]+4'); | |
| assertLatex('\\left(2+3\\right]+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('\\left(2+3+4\\right)'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('2+3+4'); | |
| }); | |
| test('backspacing open-paren of (2+3]+4 (nothing before paren group)', function() { | |
| mq.typedText('(2+3]+4'); | |
| assertLatex('\\left(2+3\\right]+4'); | |
| mq.keystroke('Left Left Left Left Left Left Backspace'); | |
| assertLatex('2+3+4'); | |
| }); | |
| function assertParenBlockNonEmpty() { | |
| var parenBlock = $(mq.el()).find('.mq-paren+span'); | |
| assert.equal(parenBlock.length, 1, 'exactly 1 paren block'); | |
| assert.ok(!parenBlock.hasClass('mq-empty'), | |
| 'paren block auto-expanded, should no longer be gray'); | |
| } | |
| test('backspacing close-bracket then open-paren of 1+(]+4 (empty paren group)', function() { | |
| mq.typedText('1+(]+4'); | |
| assertLatex('1+\\left(\\right]+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('1+\\left(+4\\right)'); | |
| assertParenBlockNonEmpty(); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1++4'); | |
| }); | |
| test('backspacing open-paren of 1+(]+4 (empty paren group)', function() { | |
| mq.typedText('1+(]+4'); | |
| assertLatex('1+\\left(\\right]+4'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1++4'); | |
| }); | |
| test('backspacing close-bracket then open-paren of 1+(] (empty paren group, nothing after)', function() { | |
| mq.typedText('1+(]'); | |
| assertLatex('1+\\left(\\right]'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+\\left(\\right)'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+'); | |
| }); | |
| test('backspacing open-paren of 1+(] (empty paren group, nothing after)', function() { | |
| mq.typedText('1+(]'); | |
| assertLatex('1+\\left(\\right]'); | |
| mq.keystroke('Left Backspace'); | |
| assertLatex('1+'); | |
| }); | |
| test('backspacing close-bracket then open-paren of (]+4 (empty paren group, nothing before)', function() { | |
| mq.typedText('(]+4'); | |
| assertLatex('\\left(\\right]+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('\\left(+4\\right)'); | |
| assertParenBlockNonEmpty(); | |
| mq.keystroke('Backspace'); | |
| assertLatex('+4'); | |
| }); | |
| test('backspacing open-paren of (]+4 (empty paren group, nothing before)', function() { | |
| mq.typedText('(]+4'); | |
| assertLatex('\\left(\\right]+4'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('+4'); | |
| }); | |
| test('rendering mismatched brackets 1+(2+3]+4 from LaTeX then backspacing close-bracket then open-paren', function() { | |
| mq.latex('1+\\left(2+3\\right]+4'); | |
| assertLatex('1+\\left(2+3\\right]+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('1+\\left(2+3+4\\right)'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('rendering mismatched brackets 1+(2+3]+4 from LaTeX then backspacing open-paren', function() { | |
| mq.latex('1+\\left(2+3\\right]+4'); | |
| assertLatex('1+\\left(2+3\\right]+4'); | |
| mq.keystroke('Left Left Left Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('rendering paren group 1+(2+3)+4 from LaTeX then backspacing close-paren then open-paren', function() { | |
| mq.latex('1+\\left(2+3\\right)+4'); | |
| assertLatex('1+\\left(2+3\\right)+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('1+\\left(2+3+4\\right)'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('rendering paren group 1+(2+3)+4 from LaTeX then backspacing open-paren', function() { | |
| mq.latex('1+\\left(2+3\\right)+4'); | |
| assertLatex('1+\\left(2+3\\right)+4'); | |
| mq.keystroke('Left Left Left Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('wrapping selection in parens 1+(2+3)+4 then backspacing close-paren then open-paren', function() { | |
| mq.typedText('1+2+3+4'); | |
| assertLatex('1+2+3+4'); | |
| mq.keystroke('Left Left Shift-Left Shift-Left Shift-Left').typedText(')'); | |
| assertLatex('1+\\left(2+3\\right)+4'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+\\left(2+3+4\\right)'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('wrapping selection in parens 1+(2+3)+4 then backspacing open-paren', function() { | |
| mq.typedText('1+2+3+4'); | |
| assertLatex('1+2+3+4'); | |
| mq.keystroke('Left Left Shift-Left Shift-Left Shift-Left').typedText('('); | |
| assertLatex('1+\\left(2+3\\right)+4'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('backspacing close-bracket of 1+(2+3] (nothing after) then typing', function() { | |
| mq.typedText('1+(2+3]'); | |
| assertLatex('1+\\left(2+3\\right]'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+\\left(2+3\\right)'); | |
| mq.typedText('+4'); | |
| assertLatex('1+\\left(2+3+4\\right)'); | |
| }); | |
| test('backspacing open-paren of (2+3]+4 (nothing before) then typing', function() { | |
| mq.typedText('(2+3]+4'); | |
| assertLatex('\\left(2+3\\right]+4'); | |
| mq.keystroke('Home Right Backspace'); | |
| assertLatex('2+3+4'); | |
| mq.typedText('1+'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('backspacing paren containing a one-sided paren 0+[(1+2)+3]+4', function() { | |
| mq.typedText('0+[1+2+3]+4'); | |
| assertLatex('0+\\left[1+2+3\\right]+4'); | |
| mq.keystroke('Left Left Left Left Left').typedText(')'); | |
| assertLatex('0+\\left[\\left(1+2\\right)+3\\right]+4'); | |
| mq.keystroke('Right Right Right Backspace'); | |
| assertLatex('0+\\left[1+2\\right)+3+4'); | |
| }); | |
| test('backspacing paren inside a one-sided paren (0+[1+2]+3)+4', function() { | |
| mq.typedText('0+[1+2]+3)+4'); | |
| assertLatex('\\left(0+\\left[1+2\\right]+3\\right)+4'); | |
| mq.keystroke('Left Left Left Left Left Backspace'); | |
| assertLatex('0+\\left[1+2+3\\right)+4'); | |
| }); | |
| test('backspacing paren containing and inside a one-sided paren (([1+2]))', function() { | |
| mq.typedText('(1+2))'); | |
| assertLatex('\\left(\\left(1+2\\right)\\right)'); | |
| mq.keystroke('Left Left').typedText(']'); | |
| assertLatex('\\left(\\left(\\left[1+2\\right]\\right)\\right)'); | |
| mq.keystroke('Right Backspace'); | |
| assertLatex('\\left(\\left(1+2\\right]\\right)'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('\\left(1+2\\right)'); | |
| }); | |
| test('auto-expanding calls .siblingCreated() on new siblings 1+((2+3))', function() { | |
| mq.typedText('1+((2+3))'); | |
| assertLatex('1+\\left(\\left(2+3\\right)\\right)'); | |
| mq.keystroke('Left Left Left Left Left Left Del'); | |
| assertLatex('1+\\left(\\left(2+3\\right)\\right)'); | |
| mq.keystroke('Left Left Del'); | |
| assertLatex('\\left(1+\\left(2+3\\right)\\right)'); | |
| // now check that the inner open-paren isn't still a ghost | |
| mq.keystroke('Right Right Right Right Del'); | |
| assertLatex('1+\\left(2+3\\right)'); | |
| }); | |
| test('that unwrapping calls .siblingCreated() on new siblings ((1+2)+(3+4))+5', function() { | |
| mq.typedText('(1+2+3+4)+5'); | |
| assertLatex('\\left(1+2+3+4\\right)+5'); | |
| mq.keystroke('Home Right Right Right Right').typedText(')'); | |
| assertLatex('\\left(\\left(1+2\\right)+3+4\\right)+5'); | |
| mq.keystroke('Right').typedText('('); | |
| assertLatex('\\left(\\left(1+2\\right)+\\left(3+4\\right)\\right)+5'); | |
| mq.keystroke('Right Right Right Right Right Backspace'); | |
| assertLatex('\\left(1+2\\right)+\\left(3+4\\right)+5'); | |
| mq.keystroke('Left Left Left Left Backspace'); | |
| assertLatex('\\left(1+2\\right)+3+4+5'); | |
| }); | |
| suite('pipes', function() { | |
| test('typing then backspacing a pipe in the middle of 1+2+3+4', function() { | |
| mq.typedText('1+2+3+4'); | |
| assertLatex('1+2+3+4'); | |
| mq.keystroke('Left Left Left').typedText('|'); | |
| assertLatex('1+2+\\left|3+4\\right|'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('backspacing close-pipe then open-pipe of 1+|2+3|+4', function() { | |
| mq.typedText('1+|2+3|+4'); | |
| assertLatex('1+\\left|2+3\\right|+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('1+\\left|2+3+4\\right|'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('backspacing open-pipe of 1+|2+3|+4', function() { | |
| mq.typedText('1+|2+3|+4'); | |
| assertLatex('1+\\left|2+3\\right|+4'); | |
| mq.keystroke('Left Left Left Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('backspacing close-pipe then open-pipe of 1+|2+3| (nothing after pipe pair)', function() { | |
| mq.typedText('1+|2+3|'); | |
| assertLatex('1+\\left|2+3\\right|'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+\\left|2+3\\right|'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1+2+3'); | |
| }); | |
| test('backspacing open-pipe of 1+|2+3| (nothing after pipe pair)', function() { | |
| mq.typedText('1+|2+3|'); | |
| assertLatex('1+\\left|2+3\\right|'); | |
| mq.keystroke('Left Left Left Left Backspace'); | |
| assertLatex('1+2+3'); | |
| }); | |
| test('backspacing close-pipe then open-pipe of |2+3|+4 (nothing before pipe pair)', function() { | |
| mq.typedText('|2+3|+4'); | |
| assertLatex('\\left|2+3\\right|+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('\\left|2+3+4\\right|'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('2+3+4'); | |
| }); | |
| test('backspacing open-pipe of |2+3|+4 (nothing before pipe pair)', function() { | |
| mq.typedText('|2+3|+4'); | |
| assertLatex('\\left|2+3\\right|+4'); | |
| mq.keystroke('Left Left Left Left Left Left Backspace'); | |
| assertLatex('2+3+4'); | |
| }); | |
| function assertParenBlockNonEmpty() { | |
| var parenBlock = $(mq.el()).find('.mq-paren+span'); | |
| assert.equal(parenBlock.length, 1, 'exactly 1 paren block'); | |
| assert.ok(!parenBlock.hasClass('mq-empty'), | |
| 'paren block auto-expanded, should no longer be gray'); | |
| } | |
| test('backspacing close-pipe then open-pipe of 1+||+4 (empty pipe pair)', function() { | |
| mq.typedText('1+||+4'); | |
| assertLatex('1+\\left|\\right|+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('1+\\left|+4\\right|'); | |
| assertParenBlockNonEmpty(); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1++4'); | |
| }); | |
| test('backspacing open-pipe of 1+||+4 (empty pipe pair)', function() { | |
| mq.typedText('1+||+4'); | |
| assertLatex('1+\\left|\\right|+4'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1++4'); | |
| }); | |
| test('backspacing close-pipe then open-pipe of 1+|| (empty pipe pair, nothing after)', function() { | |
| mq.typedText('1+||'); | |
| assertLatex('1+\\left|\\right|'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+\\left|\\right|'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+'); | |
| }); | |
| test('backspacing open-pipe of 1+|| (empty pipe pair, nothing after)', function() { | |
| mq.typedText('1+||'); | |
| assertLatex('1+\\left|\\right|'); | |
| mq.keystroke('Left Backspace'); | |
| assertLatex('1+'); | |
| }); | |
| test('backspacing close-pipe then open-pipe of ||+4 (empty pipe pair, nothing before)', function() { | |
| mq.typedText('||+4'); | |
| assertLatex('\\left|\\right|+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('\\left|+4\\right|'); | |
| assertParenBlockNonEmpty(); | |
| mq.keystroke('Backspace'); | |
| assertLatex('+4'); | |
| }); | |
| test('backspacing open-pipe of ||+4 (empty pipe pair, nothing before)', function() { | |
| mq.typedText('||+4'); | |
| assertLatex('\\left|\\right|+4'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('+4'); | |
| }); | |
| test('rendering pipe pair 1+|2+3|+4 from LaTeX then backspacing close-pipe then open-pipe', function() { | |
| mq.latex('1+\\left|2+3\\right|+4'); | |
| assertLatex('1+\\left|2+3\\right|+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('1+\\left|2+3+4\\right|'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('rendering pipe pair 1+|2+3|+4 from LaTeX then backspacing open-pipe', function() { | |
| mq.latex('1+\\left|2+3\\right|+4'); | |
| assertLatex('1+\\left|2+3\\right|+4'); | |
| mq.keystroke('Left Left Left Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('rendering mismatched paren/pipe group 1+|2+3)+4 from LaTeX then backspacing close-paren then open-pipe', function() { | |
| mq.latex('1+\\left|2+3\\right)+4'); | |
| assertLatex('1+\\left|2+3\\right)+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('1+\\left|2+3+4\\right|'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('rendering mismatched paren/pipe group 1+|2+3)+4 from LaTeX then backspacing open-pipe', function() { | |
| mq.latex('1+\\left|2+3\\right)+4'); | |
| assertLatex('1+\\left|2+3\\right)+4'); | |
| mq.keystroke('Left Left Left Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('rendering mismatched paren/pipe group 1+(2+3|+4 from LaTeX then backspacing close-pipe then open-paren', function() { | |
| mq.latex('1+\\left(2+3\\right|+4'); | |
| assertLatex('1+\\left(2+3\\right|+4'); | |
| mq.keystroke('Left Left Backspace'); | |
| assertLatex('1+\\left(2+3+4\\right)'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('rendering mismatched paren/pipe group 1+(2+3|+4 from LaTeX then backspacing open-paren', function() { | |
| mq.latex('1+\\left(2+3\\right|+4'); | |
| assertLatex('1+\\left(2+3\\right|+4'); | |
| mq.keystroke('Left Left Left Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('wrapping selection in pipes 1+|2+3|+4 then backspacing open-pipe', function() { | |
| mq.typedText('1+2+3+4'); | |
| assertLatex('1+2+3+4'); | |
| mq.keystroke('Left Left Shift-Left Shift-Left Shift-Left').typedText('|'); | |
| assertLatex('1+\\left|2+3\\right|+4'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('wrapping selection in pipes 1+|2+3|+4 then backspacing close-pipe then open-pipe', function() { | |
| mq.typedText('1+2+3+4'); | |
| assertLatex('1+2+3+4'); | |
| mq.keystroke('Left Left Shift-Left Shift-Left Shift-Left').typedText('|'); | |
| assertLatex('1+\\left|2+3\\right|+4'); | |
| mq.keystroke('Tab Backspace'); | |
| assertLatex('1+\\left|2+3+4\\right|'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('backspacing close-pipe of 1+|2+3| (nothing after) then typing', function() { | |
| mq.typedText('1+|2+3|'); | |
| assertLatex('1+\\left|2+3\\right|'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('1+\\left|2+3\\right|'); | |
| mq.typedText('+4'); | |
| assertLatex('1+\\left|2+3+4\\right|'); | |
| }); | |
| test('backspacing open-pipe of |2+3|+4 (nothing before) then typing', function() { | |
| mq.typedText('|2+3|+4'); | |
| assertLatex('\\left|2+3\\right|+4'); | |
| mq.keystroke('Home Right Backspace'); | |
| assertLatex('2+3+4'); | |
| mq.typedText('1+'); | |
| assertLatex('1+2+3+4'); | |
| }); | |
| test('backspacing pipe containing a one-sided pipe 0+|1+|2+3||+4', function() { | |
| mq.typedText('0+|1+2+3|+4'); | |
| assertLatex('0+\\left|1+2+3\\right|+4'); | |
| mq.keystroke('Left Left Left Left Left Left').typedText('|'); | |
| assertLatex('0+\\left|1+\\left|2+3\\right|\\right|+4'); | |
| mq.keystroke('Shift-Tab Shift-Tab Del'); | |
| assertLatex('0+1+\\left|2+3\\right|+4'); | |
| }); | |
| test('backspacing pipe inside a one-sided pipe 0+|1+|2+3|+4|', function() { | |
| mq.typedText('0+1+|2+3|+4'); | |
| assertLatex('0+1+\\left|2+3\\right|+4'); | |
| mq.keystroke('Home Right Right').typedText('|'); | |
| assertLatex('0+\\left|1+\\left|2+3\\right|+4\\right|'); | |
| mq.keystroke('Right Right Del'); | |
| assertLatex('0+\\left|1+2+3\\right|+4'); | |
| }); | |
| test('backspacing pipe containing and inside a one-sided pipe |0+|1+|2+3||+4|', function() { | |
| mq.typedText('0+|1+2+3|+4'); | |
| assertLatex('0+\\left|1+2+3\\right|+4'); | |
| mq.keystroke('Home').typedText('|'); | |
| assertLatex('\\left|0+\\left|1+2+3\\right|+4\\right|'); | |
| mq.keystroke('Right Right Right Right Right').typedText('|'); | |
| assertLatex('\\left|0+\\left|1+\\left|2+3\\right|\\right|+4\\right|'); | |
| mq.keystroke('Left Left Left Backspace'); | |
| assertLatex('\\left|0+1+\\left|2+3\\right|+4\\right|'); | |
| }); | |
| test('backspacing pipe containing a one-sided pipe facing same way 0+||1+2||+3', function() { | |
| mq.typedText('0+|1+2|+3'); | |
| assertLatex('0+\\left|1+2\\right|+3'); | |
| mq.keystroke('Home Right Right Right').typedText('|'); | |
| assertLatex('0+\\left|\\left|1+2\\right|\\right|+3'); | |
| mq.keystroke('Tab Tab Backspace'); | |
| assertLatex('0+\\left|\\left|1+2\\right|+3\\right|'); | |
| }); | |
| test('backspacing pipe inside a one-sided pipe facing same way 0+|1+|2+3|+4|', function() { | |
| mq.typedText('0+1+|2+3|+4'); | |
| assertLatex('0+1+\\left|2+3\\right|+4'); | |
| mq.keystroke('Home Right Right').typedText('|'); | |
| assertLatex('0+\\left|1+\\left|2+3\\right|+4\\right|'); | |
| mq.keystroke('Right Right Right Right Right Right Right Backspace'); | |
| assertLatex('0+\\left|1+\\left|2+3+4\\right|\\right|'); | |
| }); | |
| test('backspacing open-paren of mismatched paren/pipe group containing a one-sided pipe 0+(1+|2+3||+4', function() { | |
| mq.latex('0+\\left(1+2+3\\right|+4'); | |
| assertLatex('0+\\left(1+2+3\\right|+4'); | |
| mq.keystroke('Left Left Left Left Left Left').typedText('|'); | |
| assertLatex('0+\\left(1+\\left|2+3\\right|\\right|+4'); | |
| mq.keystroke('Shift-Tab Shift-Tab Del'); | |
| assertLatex('0+1+\\left|2+3\\right|+4'); | |
| }); | |
| test('backspacing open-paren of mismatched paren/pipe group inside a one-sided pipe 0+|1+(2+3|+4|', function() { | |
| mq.latex('0+1+\\left(2+3\\right|+4'); | |
| assertLatex('0+1+\\left(2+3\\right|+4'); | |
| mq.keystroke('Home Right Right').typedText('|'); | |
| assertLatex('0+\\left|1+\\left(2+3\\right|+4\\right|'); | |
| mq.keystroke('Right Right Del'); | |
| assertLatex('0+\\left|1+2+3\\right|+4'); | |
| }); | |
| }); | |
| } | |
| suite('typing outside ghost paren', function() { | |
| test('typing outside ghost paren solidifies ghost 1+(2+3)', function() { | |
| mq.typedText('1+(2+3'); | |
| assertLatex('1+\\left(2+3\\right)'); | |
| mq.keystroke('Right').typedText('+4'); | |
| assertLatex('1+\\left(2+3\\right)+4'); | |
| mq.keystroke('Left Left Left Left Left Left Left Del'); | |
| assertLatex('\\left(1+2+3\\right)+4'); | |
| }); | |
| test('selected and replaced by LiveFraction solidifies ghosts (1+2)/( )', function() { | |
| mq.typedText('1+2)/'); | |
| assertLatex('\\frac{\\left(1+2\\right)}{ }'); | |
| mq.keystroke('Left Backspace'); | |
| assertLatex('\\frac{\\left(1+2\\right)}{ }'); | |
| }); | |
| test('close paren group by typing close-bracket outside ghost paren (1+2]', function() { | |
| mq.typedText('(1+2'); | |
| assertLatex('\\left(1+2\\right)'); | |
| mq.keystroke('Right').typedText(']'); | |
| assertLatex('\\left(1+2\\right]'); | |
| }); | |
| test('close adjacent paren group before containing paren group (1+(2+3])', function() { | |
| mq.typedText('(1+(2+3'); | |
| assertLatex('\\left(1+\\left(2+3\\right)\\right)'); | |
| mq.keystroke('Right').typedText(']'); | |
| assertLatex('\\left(1+\\left(2+3\\right]\\right)'); | |
| mq.typedText(']'); | |
| assertLatex('\\left(1+\\left(2+3\\right]\\right]'); | |
| }); | |
| test('can type close-bracket on solid side of one-sided paren [](1+2)', function() { | |
| mq.typedText('(1+2'); | |
| assertLatex('\\left(1+2\\right)'); | |
| mq.moveToLeftEnd().typedText(']'); | |
| assertLatex('\\left[\\right]\\left(1+2\\right)'); | |
| }); | |
| suite('pipes', function() { | |
| test('close pipe pair from outside to the right |1+2|', function() { | |
| mq.typedText('|1+2'); | |
| assertLatex('\\left|1+2\\right|'); | |
| mq.keystroke('Right').typedText('|'); | |
| assertLatex('\\left|1+2\\right|'); | |
| mq.keystroke('Home Del'); | |
| assertLatex('\\left|1+2\\right|'); | |
| }); | |
| test('close pipe pair from outside to the left |1+2|', function() { | |
| mq.typedText('|1+2|'); | |
| assertLatex('\\left|1+2\\right|'); | |
| mq.keystroke('Home Del'); | |
| assertLatex('\\left|1+2\\right|'); | |
| mq.keystroke('Left').typedText('|'); | |
| assertLatex('\\left|1+2\\right|'); | |
| mq.keystroke('Ctrl-End Backspace'); | |
| assertLatex('\\left|1+2\\right|'); | |
| }); | |
| test('can type pipe on solid side of one-sided pipe ||||', function() { | |
| mq.typedText('|'); | |
| assertLatex('\\left|\\right|'); | |
| mq.moveToLeftEnd().typedText('|'); | |
| assertLatex('\\left|\\left|\\right|\\right|'); | |
| }); | |
| }); | |
| }); | |
| }); | |
| suite('autoCommands', function() { | |
| setup(function() { | |
| MQ.config({ | |
| autoOperatorNames: 'sin pp', | |
| autoCommands: 'pi tau phi theta Gamma sum prod sqrt nthroot' | |
| }); | |
| }); | |
| test('individual commands', function(){ | |
| mq.typedText('sum' + 'n=0'); | |
| mq.keystroke('Up').typedText('100').keystroke('Right'); | |
| assertLatex('\\sum_{n=0}^{100}'); | |
| mq.keystroke('Ctrl-Backspace'); | |
| mq.typedText('prod'); | |
| mq.typedText('n=0').keystroke('Up').typedText('100').keystroke('Right'); | |
| assertLatex('\\prod_{n=0}^{100}'); | |
| mq.keystroke('Ctrl-Backspace'); | |
| mq.typedText('sqrt'); | |
| mq.typedText('100').keystroke('Right'); | |
| assertLatex('\\sqrt{100}'); | |
| mq.keystroke('Ctrl-Backspace'); | |
| mq.typedText('nthroot'); | |
| mq.typedText('n').keystroke('Right').typedText('100').keystroke('Right'); | |
| assertLatex('\\sqrt[n]{100}'); | |
| mq.keystroke('Ctrl-Backspace'); | |
| mq.typedText('pi'); | |
| assertLatex('\\pi'); | |
| mq.keystroke('Backspace'); | |
| mq.typedText('tau'); | |
| assertLatex('\\tau'); | |
| mq.keystroke('Backspace'); | |
| mq.typedText('phi'); | |
| assertLatex('\\phi'); | |
| mq.keystroke('Backspace'); | |
| mq.typedText('theta'); | |
| assertLatex('\\theta'); | |
| mq.keystroke('Backspace'); | |
| mq.typedText('Gamma'); | |
| assertLatex('\\Gamma'); | |
| mq.keystroke('Backspace'); | |
| }); | |
| test('sequences of auto-commands and other assorted characters', function() { | |
| mq.typedText('sin' + 'pi'); | |
| assertLatex('\\sin\\pi'); | |
| mq.keystroke('Left Backspace'); | |
| assertLatex('si\\pi'); | |
| mq.keystroke('Left').typedText('p'); | |
| assertLatex('spi\\pi'); | |
| mq.typedText('i'); | |
| assertLatex('s\\pi i\\pi'); | |
| mq.typedText('p'); | |
| assertLatex('s\\pi pi\\pi'); | |
| mq.keystroke('Right').typedText('n'); | |
| assertLatex('s\\pi pin\\pi'); | |
| mq.keystroke('Left Left Left').typedText('s'); | |
| assertLatex('s\\pi spin\\pi'); | |
| mq.keystroke('Backspace'); | |
| assertLatex('s\\pi pin\\pi'); | |
| mq.keystroke('Del').keystroke('Backspace'); | |
| assertLatex('\\sin\\pi'); | |
| }); | |
| test('has lower "precedence" than operator names', function() { | |
| mq.typedText('ppi'); | |
| assertLatex('\\operatorname{pp}i'); | |
| mq.keystroke('Left Left').typedText('i'); | |
| assertLatex('\\pi pi'); | |
| }); | |
| test('command contains non-letters', function() { | |
| assert.throws(function() { MQ.config({ autoCommands: 'e1' }); }); | |
| }); | |
| test('command length less than 2', function() { | |
| assert.throws(function() { MQ.config({ autoCommands: 'e' }); }); | |
| }); | |
| test('command is a built-in operator name', function() { | |
| var cmds = ('Pr arg deg det dim exp gcd hom inf ker lg lim ln log max min sup' | |
| + ' limsup liminf injlim projlim Pr').split(' '); | |
| for (var i = 0; i < cmds.length; i += 1) { | |
| assert.throws(function() { MQ.config({ autoCommands: cmds[i] }) }, | |
| 'MQ.config({ autoCommands: "'+cmds[i]+'" })'); | |
| } | |
| }); | |
| test('built-in operator names even after auto-operator names overridden', function() { | |
| MQ.config({ autoOperatorNames: 'sin inf arcosh cosh cos cosec csc' }); | |
| // ^ happen to be the ones required by autoOperatorNames.test.js | |
| var cmds = 'Pr arg deg det exp gcd inf lg lim ln log max min sup'.split(' '); | |
| for (var i = 0; i < cmds.length; i += 1) { | |
| assert.throws(function() { MQ.config({ autoCommands: cmds[i] }) }, | |
| 'MQ.config({ autoCommands: "'+cmds[i]+'" })'); | |
| } | |
| }); | |
| suite('command list not perfectly space-delimited', function() { | |
| test('double space', function() { | |
| assert.throws(function() { MQ.config({ autoCommands: 'pi theta' }); }); | |
| }); | |
| test('leading space', function() { | |
| assert.throws(function() { MQ.config({ autoCommands: ' pi' }); }); | |
| }); | |
| test('trailing space', function() { | |
| assert.throws(function() { MQ.config({ autoCommands: 'pi ' }); }); | |
| }); | |
| }); | |
| }); | |
| suite('inequalities', function() { | |
| // assertFullyFunctioningInequality() checks not only that the inequality | |
| // has the right LaTeX and when you backspace it has the right LaTeX, | |
| // but also that when you backspace you get the right state such that | |
| // you can either type = again to get the non-strict inequality again, | |
| // or backspace again and it'll delete correctly. | |
| function assertFullyFunctioningInequality(nonStrict, strict) { | |
| assertLatex(nonStrict); | |
| mq.keystroke('Backspace'); | |
| assertLatex(strict); | |
| mq.typedText('='); | |
| assertLatex(nonStrict); | |
| mq.keystroke('Backspace'); | |
| assertLatex(strict); | |
| mq.keystroke('Backspace'); | |
| assertLatex(''); | |
| } | |
| test('typing and backspacing <= and >=', function() { | |
| mq.typedText('<'); | |
| assertLatex('<'); | |
| mq.typedText('='); | |
| assertFullyFunctioningInequality('\\le', '<'); | |
| mq.typedText('>'); | |
| assertLatex('>'); | |
| mq.typedText('='); | |
| assertFullyFunctioningInequality('\\ge', '>'); | |
| mq.typedText('<<>>==>><<=='); | |
| assertLatex('<<>\\ge=>><\\le='); | |
| }); | |
| test('typing ≤ and ≥ chars directly', function() { | |
| mq.typedText('≤'); | |
| assertFullyFunctioningInequality('\\le', '<'); | |
| mq.typedText('≥'); | |
| assertFullyFunctioningInequality('\\ge', '>'); | |
| }); | |
| suite('rendered from LaTeX', function() { | |
| test('control sequences', function() { | |
| mq.latex('\\le'); | |
| assertFullyFunctioningInequality('\\le', '<'); | |
| mq.latex('\\ge'); | |
| assertFullyFunctioningInequality('\\ge', '>'); | |
| }); | |
| test('≤ and ≥ chars', function() { | |
| mq.latex('≤'); | |
| assertFullyFunctioningInequality('\\le', '<'); | |
| mq.latex('≥'); | |
| assertFullyFunctioningInequality('\\ge', '>'); | |
| }); | |
| }); | |
| }); | |
| suite('SupSub behavior options', function() { | |
| test('charsThatBreakOutOfSupSub', function() { | |
| assert.equal(mq.typedText('x^2n+y').latex(), 'x^{2n+y}'); | |
| mq.latex(''); | |
| assert.equal(mq.typedText('x^+2n').latex(), 'x^{+2n}'); | |
| mq.latex(''); | |
| assert.equal(mq.typedText('x^-2n').latex(), 'x^{-2n}'); | |
| mq.latex(''); | |
| assert.equal(mq.typedText('x^=2n').latex(), 'x^{=2n}'); | |
| mq.latex(''); | |
| MQ.config({ charsThatBreakOutOfSupSub: '+-=<>' }); | |
| assert.equal(mq.typedText('x^2n+y').latex(), 'x^{2n}+y'); | |
| mq.latex(''); | |
| // Unary operators never break out of exponents. | |
| assert.equal(mq.typedText('x^+2n').latex(), 'x^{+2n}'); | |
| mq.latex(''); | |
| assert.equal(mq.typedText('x^-2n').latex(), 'x^{-2n}'); | |
| mq.latex(''); | |
| assert.equal(mq.typedText('x^=2n').latex(), 'x^{=2n}'); | |
| mq.latex(''); | |
| // Only break out of exponents if cursor at the end, don't | |
| // jump from the middle of the exponent out to the right. | |
| assert.equal(mq.typedText('x^ab').latex(), 'x^{ab}'); | |
| assert.equal(mq.keystroke('Left').typedText('+').latex(), 'x^{a+b}'); | |
| mq.latex(''); | |
| }); | |
| test('supSubsRequireOperand', function() { | |
| assert.equal(mq.typedText('^').latex(), '^{ }'); | |
| assert.equal(mq.typedText('2').latex(), '^2'); | |
| assert.equal(mq.typedText('n').latex(), '^{2n}'); | |
| mq.latex(''); | |
| assert.equal(mq.typedText('x').latex(), 'x'); | |
| assert.equal(mq.typedText('^').latex(), 'x^{ }'); | |
| assert.equal(mq.typedText('2').latex(), 'x^2'); | |
| assert.equal(mq.typedText('n').latex(), 'x^{2n}'); | |
| mq.latex(''); | |
| assert.equal(mq.typedText('x').latex(), 'x'); | |
| assert.equal(mq.typedText('^').latex(), 'x^{ }'); | |
| assert.equal(mq.typedText('^').latex(), 'x^{^{ }}'); | |
| assert.equal(mq.typedText('2').latex(), 'x^{^2}'); | |
| assert.equal(mq.typedText('n').latex(), 'x^{^{2n}}'); | |
| mq.latex(''); | |
| assert.equal(mq.typedText('2').latex(), '2'); | |
| assert.equal(mq.keystroke('Shift-Left').typedText('^').latex(), '^2'); | |
| mq.latex(''); | |
| MQ.config({ supSubsRequireOperand: true }); | |
| assert.equal(mq.typedText('^').latex(), ''); | |
| assert.equal(mq.typedText('2').latex(), '2'); | |
| assert.equal(mq.typedText('n').latex(), '2n'); | |
| mq.latex(''); | |
| assert.equal(mq.typedText('x').latex(), 'x'); | |
| assert.equal(mq.typedText('^').latex(), 'x^{ }'); | |
| assert.equal(mq.typedText('2').latex(), 'x^2'); | |
| assert.equal(mq.typedText('n').latex(), 'x^{2n}'); | |
| mq.latex(''); | |
| assert.equal(mq.typedText('x').latex(), 'x'); | |
| assert.equal(mq.typedText('^').latex(), 'x^{ }'); | |
| assert.equal(mq.typedText('^').latex(), 'x^{ }'); | |
| assert.equal(mq.typedText('2').latex(), 'x^2'); | |
| assert.equal(mq.typedText('n').latex(), 'x^{2n}'); | |
| mq.latex(''); | |
| assert.equal(mq.typedText('2').latex(), '2'); | |
| assert.equal(mq.keystroke('Shift-Left').typedText('^').latex(), '^2'); | |
| }); | |
| }); | |
| }); |