import { afterAll, beforeEach, describe, test, expect } from '@jest/globals'; import { getTokens, setupTex, tex2mml, expectTexError } from '#helpers'; import '#js/input/tex/begingroup/BegingroupConfiguration'; import '#js/input/tex/newcommand/NewcommandConfiguration'; import { Configuration } from '#js/input/tex/Configuration.js'; import { CommandMap } from '#js/input/tex/TokenMap.js'; import TexParser from '#js/input/tex/TexParser.js'; import { mathjax } from '#js/mathjax.js'; /**********************************************************************************/ /** * Implement a command that forces a retry error (like \require would), * but does nothing when called on the retry. */ new CommandMap('retry', { retry(parser: TexParser, _name: string) { if (!parser.options.retry) { parser.options.retry = true; mathjax.retryAfter(Promise.resolve()); } }, }); Configuration.create('retry', { handler: { macro: ['retry'] } }); /**********************************************************************************/ describe('Begingroup', () => { beforeEach(() => setupTex(['base', 'begingroup', 'newcommand', 'retry'], { formatError: (_jax: any, err: Error) => { throw err; }, }) ); test('Begingroup Def Single', () => { expect( tex2mml('\\def\\x{A} \\x \\begingroup \\def\\x{B} \\x \\endgroup \\x') ).toMatchSnapshot(); }); test('Begingroup Def Nested', () => { expect( tex2mml( '\\def\\x{A} \\x \\begingroup \\def\\x{B} \\x \\begingroup \\def\\x{C} \\x \\endgroup \\x \\endgroup \\x' ) ).toMatchSnapshot(); }); test('Begingroup Let Single', () => { expect( tex2mml('\\def\\x{A} \\x \\begingroup \\let\\x=B \\x \\endgroup \\x') ).toMatchSnapshot(); }); test('Begingroup Let Nested', () => { expect( tex2mml( '\\def\\x{A} \\x \\begingroup \\let\\x=B \\x \\begingroup \\let\\x=C \\x \\endgroup \\x \\endgroup \\x' ) ).toMatchSnapshot(); }); test('Begingroup Env Single', () => { expect( tex2mml( '\\newenvironment{test}{[}{]}\\begin{test}X\\end{test}\\begingroup\\newenvironment{test}{(}{)}\\begin{test}X\\end{test}\\endgroup\\begin{test}X\\end{test}' ) ).toMatchSnapshot(); }); test('Begingroup Delimiter Single', () => { expect( tex2mml( '\\let\\x=\\| \\left\\x A\\right\\x \\begingroup \\let\\x=| \\left\\x B \\right\\x \\endgroup \\left\\x C \\right\\x' ) ).toMatchSnapshot(); }); test('Begingroup Delimiter Nested', () => { expect( tex2mml( '\\let\\x=\\| \\left\\x A\\right\\x \\begingroup \\let\\x=| \\left\\x B \\right\\x \\begingroup \\let\\x=( \\left\\x C \\right\\x \\endgroup \\left\\x D \\right\\x \\endgroup \\left\\x E \\right\\x' ) ).toMatchSnapshot(); }); test('Begingroup Global', () => { expect( tex2mml( '\\def\\x{A} \\x \\begingroup \\def\\x{B} \\x \\global\\def\\x{C} \\x \\endgroup \\x' ) ).toMatchSnapshot(); }); test('Begingroup Global Nested', () => { expect( tex2mml( '\\def\\x{A} \\x \\begingroup \\def\\x{B} \\x \\begingroup \\gdef\\x{C} \\x \\endgroup \\x \\endgroup \\x' ) ).toMatchSnapshot(); }); test('Begingroup Global Let', () => { expect( tex2mml( '\\def\\x{A} \\x \\begingroup \\let\\x=B \\x \\global\\let\\x=C \\x \\endgroup \\x' ) ).toMatchSnapshot(); }); test('Begingroup Persists', () => { expect(tex2mml('\\def\\x{A} \\begingroup \\def\\x{B}')).toMatchSnapshot(); expect(tex2mml('\\x \\endgroup \\x')).toMatchSnapshot(); }); test('Begingroup Reset', () => { expect( tex2mml('\\def\\x{A} \\begingroup \\def\\x{B} \\begingroupReset \\x') ).toMatchSnapshot(); }); test('Begingroup End without Begin', () => { expectTexError('\\endgroup').toBe( 'Missing \\begingroup or extra \\endgroup' ); }); test('Begingroup End without Begin 2', () => { expectTexError('\\begingroup \\endgroup \\endgroup').toBe( 'Missing \\begingroup or extra \\endgroup' ); }); test('Begingroup global misplaced', () => { expectTexError('\\global\\sqrt{x}').toBe('Invalid use of \\global'); expectTexError('\\global x').toBe('Invalid use of \\global'); }); test('Begingroup reset', () => { expectTexError('\\begingroup \\begingroupReset \\endgroup').toBe( 'Missing \\begingroup or extra \\endgroup' ); }); test('Begingroup reset 2', () => { expect( tex2mml('\\def\\x{A} \\begingroup \\def\\x{B} \\begingroupReset \\x') ).toMatchSnapshot(); }); test('Begingroup let undefined', () => { expectTexError( '\\def\\x{A} \\begingroup \\let\\x=\\undefined \\x \\endgroup' ).toBe('Undefined control sequence \\x'); }); test('Begingroup let undefined 2', () => { expect( tex2mml('\\def\\x{A} \\begingroup \\let\\x=\\undefined \\endgroup \\x') ).toMatchSnapshot(); }); test('Begingroup global def undefines local delimiter', () => { expect( tex2mml( '\\def\\x{A} \\x \\begingroup \\let\\x=\\| \\x \\begingroup \\gdef\\x{C} \\x \\endgroup \\x \\endgroup \\x' ) ).toMatchSnapshot(); }); test('Begingroup global let delimiter undefines local def', () => { expect( tex2mml( '\\let\\x=| \\x \\begingroup \\def\\x{A} \\x \\begingroup \\global\\let\\x=\\| \\x \\endgroup \\x \\endgroup \\x' ) ).toMatchSnapshot(); }); test('Begingroup sandbox', () => { expect( tex2mml( '\\def\\x{A} \\begingroupSandbox \\def\\x{B} \\begingroupReset \\x' ) ).toMatchSnapshot(); }); test('Begingroup double sandbox', () => { expect( tex2mml( '\\def\\x{A} \\begingroupSandbox \\def\\x{B} \\begingroupSandbox \\x' ) ).toMatchSnapshot(); }); test('Begingroup sandbox not ended', () => { expectTexError('\\begingroupSandbox \\endgroup').toBe( 'Missing \\begingroup or extra \\endgroup' ); }); test('Begingroup sandbox redefine', () => { expectTexError('\\let\\begingroupSandbox=\\undefined').toBe( "The control sequence \\begingroupSandbox can't be redefined" ); expectTexError('\\def\\begingroupSandbox{x}').toBe( "The control sequence \\begingroupSandbox can't be redefined" ); expectTexError('\\newcommand{\\begingroupSandbox}{x}').toBe( "The control sequence \\begingroupSandbox can't be redefined" ); }); test('Begingroup with retry', async () => { await expect( mathjax.handleRetriesFor(() => tex2mml('\\sin \\begingroup\\def\\sin{SIN}\\retry\\endgroup') ) ).resolves.toBe( ` sin ` ); }); test('Begingroup sandbox with retry', async () => { tex2mml('\\def\\x{A}\\begingroupSandbox'); await expect( mathjax.handleRetriesFor(() => tex2mml('\\x \\begingroup\\def\\x{B}\\retry\\endgroup') ) ).resolves.toBe( ` A ` ); }); test('Begingroup retry error', async () => { await expect( mathjax .handleRetriesFor(() => tex2mml('\\begingroup\\retry\\endgroup\\endgroup') ) .catch((e) => e.message) ).resolves.toBe('Missing \\begingroup or extra \\endgroup'); }); test('Begingroup sandbox retry error', async () => { tex2mml('\\begingroupSandbox'); await expect( mathjax .handleRetriesFor(() => tex2mml('\\begingroup\\retry\\endgroup\\endgroup') ) .catch((e) => e.message) ).resolves.toBe('Missing \\begingroup or extra \\endgroup'); }); }); /**********************************************************************************/ afterAll(() => getTokens('begingroup'));