import { afterAll, beforeEach, describe, expect, it } from '@jest/globals';
import { getTokens, setupTex, tex2mml, expectTexError } from '#helpers';
import '#js/input/tex/newcommand/NewcommandConfiguration';
import '#js/input/tex/ams/AmsConfiguration';
import '#js/input/tex/colorv2/ColorV2Configuration';

/**********************************************************************************/

describe('Newcommand', () => {
  beforeEach(() => setupTex(['base', 'newcommand']));

  it('Newcommand Simple', () => {
    expect(tex2mml('\\newcommand{\\sum}{2 + 3}\\sum')).toMatchSnapshot();
  });

  it('Newcommand Arg', () => {
    expect(
      tex2mml('\\renewcommand{\\sum}[1]{2 #1 3}\\sum{*}')
    ).toMatchSnapshot();
  });

  it('Newcommand Optional', () => {
    expect(
      tex2mml('\\renewcommand{\\sum}[1][+]{2 #1 3}\\sum\\sum[*]')
    ).toMatchSnapshot();
  });

  it('Newcommand Arg Optional', () => {
    expect(
      tex2mml('\\renewcommand{\\sum}[2][+]{2 #1 3 #2 4}\\sum{+}\\sum[*]{+}')
    ).toMatchSnapshot();
  });

  it('Newenvironment Optional', () => {
    expect(
      tex2mml(
        '\\newenvironment{argument}[1][a]{\\textbf{Argument #1:}}{aa}\\begin{argument}[c]b\\end{argument}'
      )
    ).toMatchSnapshot();
  });

  it('Newenvironment Optional Noarg', () => {
    expect(
      tex2mml(
        '\\newenvironment{argument}[1][a]{\\textbf{Argument #1:}}{aa}\\begin{argument}b\\end{argument}'
      )
    ).toMatchSnapshot();
  });

  it('Newenvironment Arg Optional', () => {
    expect(
      tex2mml(
        '\\renewenvironment{argument}[2][a]{\\textbf{Argument #1(#2):}}{aa}\\begin{argument}[c]{3}b\\end{argument}'
      )
    ).toMatchSnapshot();
  });

  it('Def Double Let', () => {
    expect(
      tex2mml(
        '\\def\\bar{h}\\let\\fooi\\bar\\def\\fooii{\\bar}\\fooi +\\fooii\\def\\bar{g}\\fooi +\\fooii'
      )
    ).toMatchSnapshot();
  });

  it('Def ReDef', () => {
    expect(
      tex2mml(
        '\\def\\foo{a + b}\\foo\\def\\foo#1{a #1 b}\\foo{-}\\def\\foo#1#2{#2 #1 b}\\foo{-}{x}'
      )
    ).toMatchSnapshot();
  });

  it('Let Brace Equal', () => {
    expect(tex2mml('\\let\\be={ \\be a}')).toMatchSnapshot();
  });

  it('Let Brace', () => {
    expect(tex2mml('\\let\\be{ \\be a}')).toMatchSnapshot();
  });

  it('Let Caret', () => {
    expect(tex2mml('\\let\\car^ a\\car b')).toMatchSnapshot();
  });

  it('Let Brace Delim', () => {
    expect(tex2mml('\\let\\lb=\\{ \\lb \\frac{1}{2} \\}')).toMatchSnapshot();
  });

  it('Let Paren Delim', () => {
    expect(tex2mml('\\let\\lb( \\lb \\frac{1}{2})')).toMatchSnapshot();
  });

  it('Let Relet', () => {
    expect(
      tex2mml('\\let\\al\\alpha\\al\\alpha\\let\\al\\aleph\\al\\alpha')
    ).toMatchSnapshot();
  });

  it('Let Let', () => {
    expect(
      tex2mml('\\let\\al\\alpha\\al\\alpha\\let\\alpha\\beta\\al\\alpha')
    ).toMatchSnapshot();
  });

  it('Def Let', () => {
    expect(
      tex2mml('\\def\\bar[#1]#2{#1 + #2}\\bar[a]{b}\\let\\foo\\bar\\foo[c]{d}')
    ).toMatchSnapshot();
  });

  it('Newcommand Let', () => {
    expect(
      tex2mml(
        '\\newcommand{\\bar}[2][1]{#1 + #2}\\bar[a]{b}\\let\\foo\\bar\\foo[c]{d}'
      )
    ).toMatchSnapshot();
  });

  it('Let Circular Macro', () => {
    expect(
      tex2mml(
        '\\let\\kk\\alpha\\kk\\let\\rr\\beta\\rr\\let\\rr\\kk\\let\\kk\\beta\\kk\\rr'
      )
    ).toMatchSnapshot();
  });

  it('Let Brace Equal Stretchy', () => {
    expect(
      tex2mml('\\let\\lb=\\{\\left\\lb \\frac{1}{2} \\right\\}')
    ).toMatchSnapshot();
  });

  it('Let Paren Stretchy', () => {
    expect(
      tex2mml('\\let\\lb( \\left\\lb \\frac{1}{2} \\right)')
    ).toMatchSnapshot();
  });

  it('Let Fn', () => {
    expect(tex2mml('\\let\\ll\\sin\\ll(x)')).toMatchSnapshot();
  });

  it('Let Fn Double', () => {
    expect(
      tex2mml('\\let\\ll\\sin\\ll(x)\\let\\rr\\ll\\let\\ll\\cos\\rr(x)\\ll(x)')
    ).toMatchSnapshot();
  });

  it('Let Fn Circular', () => {
    expect(
      tex2mml(
        '\\let\\save\\sin\\let\\sin\\cos\\let\\cos\\tan\\let\\tan\\save\\sin(x)\\cos(x)\\tan(x)'
      )
    ).toMatchSnapshot();
  });

  it('Let Paren Circular', () => {
    expect(
      tex2mml(
        '\\let\\lp(\\let\\rp)\\let\\mp\\rp\\left\\lp \\frac{a}{b}\\middle\\mp c \\right\\rp'
      )
    ).toMatchSnapshot();
  });

  it('Let Angle Circular', () => {
    expect(
      tex2mml(
        '\\let\\lp\\langle\\let\\rp\\rangle\\let\\mp\\rp\\left\\lp \\frac{a}{b}\\middle\\mp c \\right\\rp'
      )
    ).toMatchSnapshot();
  });

  it('Let Circular Character', () => {
    expect(
      tex2mml(
        '\\let\\a a\\let\\b b\\a \\b\\let\\c\\a\\let\\a c\\c \\a\\let\\d=\\c\\let\\c\\b\\d \\c'
      )
    ).toMatchSnapshot();
  });

  it('Let Self', () => {
    expectTexError('\\let\\x\\x \\x').toBe('Undefined control sequence \\x');
  });

  it('Let Overwrite Sqrt Choose', () => {
    expect(tex2mml('\\let\\sqrt\\choose a\\sqrt b')).toMatchSnapshot();
  });

  it('Def Optional Brace', () => {
    expect(tex2mml('\\def\\bar[#1]#2{#1 + #2}\\bar[{a}]{b}')).toMatchSnapshot();
  });

  it('Def Options CS', () => {
    expect(
      tex2mml('\\def\\bar[#1]#2{#1 + #2}\\bar[\\sqrt{2}]{b}')
    ).toMatchSnapshot();
  });

  it('Def Template Matching', () => {
    expect(
      tex2mml(
        '\\def\\ending{+}\\def\\test#1\\end{[#1]} \\test a\\ending b\\end'
      )
    ).toMatchSnapshot();
  });

  it('Def Template Brace Removal', () => {
    expect(
      tex2mml('\\def\\test#1\\end{\\text{#1}} \\test{a b}\\end')
    ).toMatchSnapshot();
  });

  it('Def Template Brace Retention', () => {
    expect(
      tex2mml('\\def\\test#1\\end{\\text{#1}} \\test{a}{b}\\end')
    ).toMatchSnapshot();
  });

  it('Def Hash Replacement', () => {
    expect(
      tex2mml('\\def\\x#1{\\def\\y##1#1{[##1]}\\y} \\x\\X abc \\X')
    ).toMatchSnapshot();
  });

  it('Def insignificant spaces', () => {
    expect(tex2mml('\\def\\x  #1  {[#1]} \\x{x}')).toMatchSnapshot();
  });

  it('Def significant spaces 1', () => {
    expectTexError('\\def\\x#1 #2{[#1,#2]} \\x{a}{b}').toBe('Runaway argument for \\x?');
    expect(tex2mml('\\def\\x#1 #2{[#1,#2]} \\x{a} {b}')).toMatchSnapshot();
  });

  it('Def significant spaces 2', () => {
    expectTexError('\\def\\x#1 #2 {[#1,#2]} \\x{a}{b}').toBe('Runaway argument for \\x?');
    expectTexError('\\def\\x#1 #2 {[#1,#2]} \\x{a} {b}').toBe('Runaway argument for \\x?');
    expect(tex2mml('\\def\\x#1 #2{[#1,#2]} \\x{a} {b} ')).toMatchSnapshot();
  });
});

/**********************************************************************************/

describe('Newcommand Color v2', () => {
  beforeEach(() => setupTex(['base', 'newcommand', 'colorv2']));

  it('Newenvironment Empty', () => {
    expect(
      tex2mml(
        '\\newenvironment{myHeartEnv}{\\color{purple}{\\heartsuit}\\kern-2.5pt\\color{green}{\\heartsuit}}{\\text{ forever}}\\begin{myHeartEnv}\\end{myHeartEnv}'
      )
    ).toMatchSnapshot();
  });

  it('Newenvironment Content', () => {
    expect(
      tex2mml(
        '\\newenvironment{myHeartEnv}{\\color{purple}{\\heartsuit}\\kern-2.5pt\\color{green}{\\heartsuit}}{\\text{ forever}}\\begin{myHeartEnv}  2+3\\end{myHeartEnv}'
      )
    ).toMatchSnapshot();
  });

  it('Newenvironment Nested Double', () => {
    expect(
      tex2mml(
        '\\newenvironment{myHeartEnv}{\\color{purple}{\\heartsuit}\\kern-2.5pt\\color{green}{\\heartsuit}}{\\text{ forever}}\\newenvironment{yourHeartEnv}{\\color{blue}{\\heartsuit}\\kern-2.5pt\\color{black}{\\heartsuit}}{\\text{ never}}\\begin{myHeartEnv}\\begin{yourHeartEnv}a\\end{yourHeartEnv}\\end{myHeartEnv}'
      )
    ).toMatchSnapshot();
  });

  it('Newenvironment Nested Double 2', () => {
    expect(
      tex2mml(
        '\\newenvironment{myHeartEnv}{\\color{purple}{\\heartsuit}\\kern-2.5pt\\color{green}{\\heartsuit}}{\\text{ forever}}\\newenvironment{yourHeartEnv}{\\color{blue}{\\heartsuit}\\kern-2.5pt\\color{black}{\\heartsuit}}{\\text{ never}}\\newenvironment{theirHeartEnv}{\\color{blue}{\\heartsuit}\\kern-2.5pt\\color{black}{\\heartsuit}}{\\text{ never}}\\begin{myHeartEnv}\\begin{yourHeartEnv}a\\end{yourHeartEnv}\\begin{theirHeartEnv}b\\end{theirHeartEnv}\\end{myHeartEnv}'
      )
    ).toMatchSnapshot();
  });

  it('Newenvironment Nested Triple', () => {
    expect(
      tex2mml(
        '\\newenvironment{myHeartEnv}{\\color{purple}{\\heartsuit}\\kern-2.5pt\\color{green}{\\heartsuit}}{\\text{ forever}}\\newenvironment{yourHeartEnv}{\\color{blue}{\\heartsuit}\\kern-2.5pt\\color{black}{\\heartsuit}}{\\text{ never}}\\newenvironment{theirHeartEnv}{\\color{blue}{\\heartsuit}\\kern-2.5pt\\color{black}{\\heartsuit}}{\\text{ never}}\\begin{myHeartEnv}\\begin{yourHeartEnv}a\\begin{theirHeartEnv}b\\end{theirHeartEnv}\\end{yourHeartEnv}\\end{myHeartEnv}'
      )
    ).toMatchSnapshot();
  });

  it('Newenvironment Nested Triple Text', () => {
    expect(
      tex2mml(
        '\\newenvironment{myHeartEnv}{\\color{purple}{\\heartsuit}\\kern-2.5pt\\color{green}{\\heartsuit}}{\\text{ forever}}\\newenvironment{yourHeartEnv}{\\color{blue}{\\heartsuit}\\kern-2.5pt\\color{black}{\\heartsuit}}{\\text{ never}}\\newenvironment{theirHeartEnv}{\\color{blue}{\\heartsuit}\\kern-2.5pt\\color{black}{\\heartsuit}}{\\text{ never}}\\begin{myHeartEnv}\\begin{yourHeartEnv}a\\begin{theirHeartEnv}b\\end{theirHeartEnv}c\\end{yourHeartEnv}d\\end{myHeartEnv}'
      )
    ).toMatchSnapshot();
  });

  it('Newenvironment Nested Error', () => {
    expectTexError(
      '\\newenvironment{myHeartEnv}{\\color{purple}{\\heartsuit}\\kern-2.5pt\\color{green}{\\heartsuit}}{\\text{ forever}}\\newenvironment{yourHeartEnv}{\\color{blue}{\\heartsuit}\\kern-2.5pt\\color{black}{\\heartsuit}}{\\text{ never}}\\newenvironment{theirHeartEnv}{\\color{blue}{\\heartsuit}\\kern-2.5pt\\color{black}{\\heartsuit}}{\\text{ never}}\\begin{myHeartEnv}\\begin{yourHeartEnv}a\\begin{theirHeartEnv}b\\end{yourHeartEnv}\\end{theirHeartEnv}\\end{myHeartEnv}'
    ).toBe('\\begin{theirHeartEnv} ended with \\end{yourHeartEnv}');
  });
});

/**********************************************************************************/

describe('Newcommand Ams', () => {
  beforeEach(() => setupTex(['base', 'newcommand', 'ams']));

  it('Newenvironment Align', () => {
    expectTexError(
      '\\newenvironment{proof}{\\textbf{Proof:}}{\\begin{align} \\blacksquare \\end{align}}\\begin{proof}a=b\\end{proof}'
    ).toBe('Erroneous nesting of equation structures');
  });

  it('Newenvironment Align End', () => {
    expectTexError(
      '\\newenvironment{proof}{\\begin{align}\\textbf{Proof:}}{\\end{align}}\\begin{proof}a=b\\end{proof}'
    ).toBe('Erroneous nesting of equation structures');
  });

  it('Newenvironment Align Split', () => {
    expectTexError(
      '\\newenvironment{proof}{\\begin{align}\\textbf{Proof:}&}{ \\begin{split} 5 \\end{split}&& \\blacksquare\\end{align}}\\begin{proof}a&=b\\end{proof}'
    ).toBe('Erroneous nesting of equation structures');
  });

  it('Let Bar', () => {
    expect(
      tex2mml('\\let\\b\\lvert\\let\\lvert\\langle\\vert\\b\\lvert')
    ).toMatchSnapshot();
  });

  it('Let Bar Stretchy', () => {
    expect(
      tex2mml('\\let\\b\\lvert\\let\\lvert\\langle\\left\\b q \\right\\lvert')
    ).toMatchSnapshot();
  });
});

/**********************************************************************************/

describe('NewcommandError', () => {
  beforeEach(() => setupTex(['base', 'newcommand']));

  it('No Sequence', () => {
    expectTexError('\\def\\bar[#1]#3{}').toBe(
      'Parameters for \\bar must be numbered sequentially'
    );
  });

  it('No CS', () => {
    expectTexError('\\def{\\bar}[#1]#2{}').toBe(
      '\\def must be followed by a control sequence'
    );
  });

  it('Illegal Hash', () => {
    expectTexError('\\def\\bar[##1]#2{#1}').toBe(
      'Illegal use of # in template for \\bar'
    );
  });

  it('No Replacement', () => {
    expectTexError('\\def\\bar[#1]#2').toBe(
      'Missing replacement string for definition of \\def'
    );
  });

  it('Runaway Argument', () => {
    expectTexError('\\def\\bar[#1]#2{}\\bar[').toBe(
      'Runaway argument for \\bar?'
    );
  });

  it('Illegal CS', () => {
    expectTexError('\\newcommand{\\11}{a}').toBe(
      'Illegal control sequence name for \\newcommand'
    );
  });

  it('Illegal Parameter Number', () => {
    expectTexError('\\newenvironment{hh}[a]{}{}').toBe(
      'Illegal number of parameters specified in \\newenvironment'
    );
  });

  it('Let Undefined CS', () => {
    expectTexError('\\let\\aa\\bb \\aa').toBe(
      'Undefined control sequence \\aa'
    );
  });

  it('Missing Arguments', () => {
    expectTexError('\\def\\bar[#1]#2#3{c + c}\\bar').toBe(
      "Use of \\bar doesn't match its definition"
    );
  });

  it('Single Let Error', () => {
    expectTexError('\\let\\aa\\textbf\\let\\bb\\aa\\aa').toBe(
      'Missing argument for \\aa'
    );
  });

  it('Double Let Error', () => {
    expectTexError('\\let\\aa\\textbf\\let\\bb\\aa\\bb').toBe(
      'Missing argument for \\bb'
    );
  });

  it('Triple Let Error', () => {
    expectTexError(
      '\\let\\aa\\textbf\\let\\bb\\aa\\let\\textbf\\sqrt\\textbf[1]'
    ).toBe('Missing argument for \\textbf');
  });

  it('Illegal Argument Number', () => {
    expectTexError('\\newcommand{\\foo}[a]{#1 + #2}').toBe(
      'Illegal number of parameters specified in \\newcommand'
    );
  });

  it('Optional Brace Error', () => {
    expectTexError('\\def\\bar[{#1}]#2{#1 + #2}').toBe(
      "You can't use 'macro parameter character #' in math mode"
    );
  });

  it('Missing End Error', () => {
    expectTexError('\\newenvironment{env}{aa}{bb}\\begin{env}cc').toBe(
      'Missing \\end{env}'
    );
  });

  it('Hash Error', () => {
    expectTexError('\\def\\x#1{a #1 b #c} \\x{a}').toBe(
      'Illegal macro parameter reference'
    );
  });

  it('Recursive Macro', () => {
    expectTexError('\\def\\x{\\x} \\x').toBe(
      'MathJax maximum macro substitution count exceeded; is here a recursive macro call?'
    );
  });

  it('Recursive Environment', () => {
    expectTexError(
      '\\newenvironment{error}{\\begin{error}}{\\end{error}} \\begin{error}\\end{error}'
    ).toBe(
      'MathJax maximum substitution count exceeded; is there a recursive latex environment?'
    );
  });
});

/**********************************************************************************/

describe('Newcommand Overrides', () => {
  beforeEach(() => setupTex(['base', 'newcommand']));

  it('Let def macro be undefined', () => {
    expectTexError('\\def\\test{error} \\let\\test=\\undefined \\test').toBe(
      'Undefined control sequence \\test'
    );
  });

  it('Let existing macro be undefined', () => {
    expectTexError('\\let\\sqrt=\\undefined \\sqrt{x}').toBe(
      'Undefined control sequence \\sqrt'
    );
  });

  it('Let existing delimiter be undefined', () => {
    expectTexError('\\let\\|=\\undefined \\left\\| X \\right\\|').toBe(
      'Missing or unrecognized delimiter for \\left'
    );
  });

  it('Let after def of existing macro be undefined', () => {
    expectTexError('\\def\\sqrt{X} \\let\\sqrt=\\undefined \\sqrt{x}').toBe(
      'Undefined control sequence \\sqrt'
    );
  });

  it('Def overrides let delimiter', () => {
    expectTexError(
      '\\let\\test=\\| \\def\\test{x} \\left\\test X \\right\\test'
    ).toBe('Missing or unrecognized delimiter for \\left');
  });

  it('Def overrides let delimiter as macro', () => {
    expect(tex2mml('\\let\\test=\\| \\def\\test{x} \\test')).toMatchSnapshot();
  });

  it('Def overrides existing delimiter', () => {
    expectTexError('\\def\\|{x} \\left\\| X \\right\\|').toBe(
      'Missing or unrecognized delimiter for \\left'
    );
  });

  it('Def overrides existing delimiter as macro', () => {
    expect(tex2mml('\\def\\|{x} \\|')).toMatchSnapshot();
  });

  it('Let overrides def macro', () => {
    expect(
      tex2mml('\\def\\test{x} \\let\\test=\\| \\test X \\test')
    ).toMatchSnapshot();
  });

  it('Let overrides def macro as delimiter', () => {
    expect(
      tex2mml('\\def\\test{x} \\let\\test=\\| \\left\\test X \\right\\test')
    ).toMatchSnapshot();
  });

  it('Let overrides existing macro', () => {
    expect(tex2mml('\\let\\sqrt=\\| \\sqrt X')).toMatchSnapshot();
  });

  it('Let overrides existing macro as delimiter', () => {
    expect(
      tex2mml('\\let\\sqrt=\\| \\left\\sqrt X \\right\\sqrt')
    ).toMatchSnapshot();
  });

  it('Let overrides delimiter', () => {
    expectTexError('\\let\\|=\\sqrt \\left\\| X \\right\\|').toBe(
      'Missing or unrecognized delimiter for \\left'
    );
  });

  it('Let overrides delimiter as macro', () => {
    expect(tex2mml('\\let\\|=\\sqrt \\| X')).toMatchSnapshot();
  });

  it('Let of character macro overrides delimiter', () => {
    expectTexError('\\let\\|=\\alpha \\left\\| X \\right\\|').toBe(
      'Missing or unrecognized delimiter for \\left'
    );
  });

  it('Let of character creates delimiter', () => {
    expect(
      tex2mml('\\let\\test=< \\left\\test X \\right\\test')
    ).toMatchSnapshot();
  });

  it('Let of character overrides def', () => {
    expect(tex2mml('\\def\\test{X}\\let\\test=< \\test')).toMatchSnapshot();
  });
});

/**********************************************************************************/

describe('Nested Environments', () => {
  beforeEach(() => setupTex(['base', 'ams', 'newcommand']));

  it('Newenvironment with Begin', () => {
    expect(
      tex2mml(
        [
          '\\newenvironment{boxed}{\\begin{array}{|c|c|}\\hline}{\\\\\\hline\\end{array}}',
          '\\begin{boxed}a&b\\\\c&d\\end{boxed}',
        ].join('')
      )
    ).toMatchSnapshot();
  });

  it('Environments Nested', () => {
    expect(
      tex2mml(
        [
          '\\newenvironment{boxed}{\\begin{array}{|c|c|}\\hline}{\\\\\\hline\\end{array}}',
          '\\begin{boxed}\\begin{boxed}a&b\\\\c&d\\end{boxed} & X \\end{boxed}',
        ].join('')
      )
    ).toMatchSnapshot();
  });

  it('Environments Intermixed', () => {
    expect(
      tex2mml(
        [
          '\\newenvironment{a}{\\begin{b}}{\\end{b}}',
          '\\newenvironment{b}{x}{y}',
          '\\begin{a} ... \\end{b}\\begin{b}\\end{a}',
        ].join('')
      )
    ).toMatchSnapshot();
  });

  it('Nested Begins', () => {
    expect(
      tex2mml(
        '\\newenvironment{a}{x}{y}\\newenvironment{b}{p}{q}\\begin{a}\\begin{b}X\\end{b}\\end{a}'
      )
    ).toMatchSnapshot();
  });

  it('Dangling End', () => {
    expectTexError(
      '\\newenvironment{a}{x}{y\\end{a}}\\begin{a} ... \\end{a}'
    ).toBe('Missing \\begin{a} or extra \\end{a}');
  });

  it('Nested Dangling End', () => {
    expectTexError(
      '\\newenvironment{a}{\\begin{b}}{\\end{b}}\\newenvironment{b}{x}{y\\end{b}}\\begin{a}X\\end{a}'
    ).toBe('\\begin{a} ended with \\end{b}');
  });

  it('Badly Nested Begins', () => {
    expectTexError(
      '\\newenvironment{a}{x}{y}\\newenvironment{b}{p}{q}\\begin{a}\\begin{b} ... \\end{a}\\end{b}'
    ).toBe('\\begin{b} ended with \\end{a}');
  });

  it('Ended by Wrong Environment', () => {
    expectTexError('\\newenvironment{a}{x}{y}\\begin{a} X \\end{cases}').toBe(
      '\\begin{a} ended with \\end{cases}'
    );
  });

  it('Unbalanced Ends 1', () => {
    expectTexError(
      '\\newenvironment{a}{a}{b\\end{a}}\\newenvironment{b}{x}{y}\\begin{a}\\begin{b}...\\end{b}\\end{a}'
    ).toBe('Missing \\begin{a} or extra \\end{a}');
  });

  it('Unbalanced Ends 2', () => {
    expectTexError(
      '\\newenvironment{a}{a}{b\\end{a}}\\newenvironment{b}{x}{y}\\begin{b}\\begin{a}...\\end{a}\\end{b}'
    ).toBe('\\begin{b} ended with \\end{a}');
  });

  it('Triple Nesting', () => {
    expectTexError(
      [
        '\\newenvironment{c}{x}{\\end{a}y}',
        '\\newenvironment{b}{begin{c}x}{\\end{c}y}',
        '\\newenvironment{a}{\\begin{b}x}{\\end{b}y}',
        '\\begin{a} ... ',
      ].join('')
    ).toBe('Missing \\end{b}');
  });
});

/**********************************************************************************/

  afterAll(() => getTokens('newcommand'));
