Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions testsuite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"#js/*": "../mjs/*",
"#source/*": "../components/mjs/*",
"#src/*": "./src/*",
"#helpers/*": "./js/src/*",
"#helpers": "./js/src/index.js"
},
"dependencies": {
Expand Down
1 change: 1 addition & 0 deletions testsuite/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './setupTex.js';
export * from './traps.js';
100 changes: 12 additions & 88 deletions testsuite/src/setupTex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ import { mathjax } from '#js/mathjax.js';
import { OptionList } from '#js/util/Options.js';
import { tmpJsonFile } from '#src/constants.js';
import * as fs from 'fs';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { init } from '#source/node-main/node-main.mjs';
import { expect } from '@jest/globals';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { source } from '#source/source.js';
import { Locale } from '#js/util/Locale.js';
import {
trapErrors,
trapAsyncErrors,
throwTexErrors,
throwCompileErrors,
} from './traps.js';

declare const MathJax: any;
type MATHITEM = MathItem<any, any, any>;
Expand Down Expand Up @@ -57,87 +59,6 @@ export const toMathML = (node: MmlNode) => visitor.visitTree(node);

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

/**
* Trap output produced while running code.
*
* @param {string} method The console method to trap.
* @param {Function} code The code to run.
* @returns {string} The output sent to the given method.
*/
export function trapOutput(method: string, code: () => void): string {
const saved = (console as any)[method];
let message = '';
(console as any)[method] = (...msg: any[]) => {
message += (message ? '\n' : '') + msg.join(' ');
};
code();
(console as any)[method] = saved;
return message;
}

/**
* Trap errors produced while running code.
*
* @param {Function} code The code to run.
* @returns {string} The error message produced.
*/
export function trapErrors(code: () => void): string {
let message = '(no error)';
reportErrors = true;
try {
code();
} catch (e) {
message = e.message;
}
reportErrors = false;
return message;
}

/**
* Trap errors produced while running code.
*
* @param {Function} code The code to run.
* @returns {string} The error message produced.
*/
export async function trapAsyncErrors(code: () => Promise<void>) {
let message = '(no error)';
reportErrors = true;
await code().catch((e) => {
message = e.message;
});
reportErrors = false;
return message;
}

/**
* When true, errors will throw rather than produce merror elements.
*/
let reportErrors = false;

/**
* Configuration that causes TeX errors to throw rather than
* generate merror elements, so we can trap them with trapErrors().
*/
export const throwTexErrors = {
formatError(jax: any, err: Error) {
if (reportErrors) throw err;
return jax.formatError(err);
},
};

/**
* Configuration that causes compile errors to throw rather than
* generate merror elements, so we can trap them with trapErrors().
*/
export const throwCompileErrors = {
options: {
compileError(jax: any, math: any, err: Error) {
if (reportErrors) throw err;
return jax.compileError(math, err);
},
},
};

/**
* Trap TeX processing errors and return an expect() result
*
Expand Down Expand Up @@ -182,11 +103,12 @@ export function expectTypesetError(
*
* @param {string[]} packages The TeX packages to configure
* @param {OptionList} options The TeX options to include
* @returns {Promise<void[]>} The promise for when the locale is set up
*/
export function setupTex(
packages: PackageList = ['base'],
options: OptionList = {}
) {
): Promise<void[]> {
const parserOptions = Object.assign(
{},
{ packages },
Expand All @@ -206,11 +128,12 @@ export function setupTex(
*
* @param {string[]} packages The TeX packages to configure
* @param {OptionList} options The TeX options to include
* @returns {Promise<void[]>} The promise for when the locale is set up
*/
export function setupTexRender(
packages: PackageList = ['base'],
options: OptionList = {}
) {
): Promise<void[]> {
const parserOptions = Object.assign(
{},
{ packages: packages, inlineMath: { '[+]': [['$', '$']] } },
Expand Down Expand Up @@ -295,11 +218,12 @@ import { SVG } from '#js/output/svg.js';
*
* @param {string[]} packages The TeX packages to configure
* @param {OptionList} options The TeX options to include
* @returns {Promise<void[]>} The promise for when the locale is set up
*/
export function setupTexWithOutput(
packages: string[] = ['base'],
options: OptionList = {}
) {
): Promise<void[]> {
const parserOptions = Object.assign({}, { packages: packages }, options);
const tex = new TeX(parserOptions);
const html = new HTMLDocument('', adaptor, {
Expand Down
103 changes: 103 additions & 0 deletions testsuite/src/traps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**
* Trap output produced while running code.
*
* @param {string} method The console method to trap.
* @param {Function} code The code to run.
* @returns {string} The output sent to the given method.
*/
export function trapOutput(method: string, code: () => void): string {
const saved = (console as any)[method];
let message = '';
(console as any)[method] = (...msg: any[]) => {
message += (message ? '\n' : '') + msg.join(' ');
};
code();
(console as any)[method] = saved;
return message;
}

/**
* Trap errors produced while running code.
*
* @param {Function} code The code to run.
* @returns {string} The error message produced.
*/
export function trapErrors(code: () => void): string {
let message = '(no error)';
reportErrors = true;
try {
code();
} catch (e) {
message = e.message;
}
reportErrors = false;
return message;
}

/**
* Trap output produced while running async code.
*
* @param {string} method The console method to trap.
* @param {Function} code The code to run.
* @returns {string} The output sent to the given method.
*/
export async function trapAsyncOutput(
method: string,
code: () => Promise<void>
): Promise<string> {
const saved = (console as any)[method];
let message = '';
(console as any)[method] = (...msg: any[]) => {
message += (message ? '\n' : '') + msg.join(' ');
};
await code();
(console as any)[method] = saved;
return message;
}

/**
* Trap errors produced while running async code.
*
* @param {Function} code The code to run.
* @returns {string} The error message produced.
*/
export async function trapAsyncErrors(
code: () => Promise<void>
): Promise<string> {
let message = '(no error)';
reportErrors = true;
await code().catch((e) => {
message = e.message;
});
reportErrors = false;
return message;
}

/**
* When true, errors will throw rather than produce merror elements.
*/
let reportErrors = false;

/**
* Configuration that causes TeX errors to throw rather than
* generate merror elements, so we can trap them with trapErrors().
*/
export const throwTexErrors = {
formatError(jax: any, err: Error) {
if (reportErrors) throw err;
return jax.formatError(err);
},
};

/**
* Configuration that causes compile errors to throw rather than
* generate merror elements, so we can trap them with trapErrors().
*/
export const throwCompileErrors = {
options: {
compileError(jax: any, math: any, err: Error) {
if (reportErrors) throw err;
return jax.compileError(math, err);
},
},
};
6 changes: 3 additions & 3 deletions testsuite/tests/input/tex/Tex.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ describe('Configuration', () => {
() => new TeX({ packages: ['base', 'undefined'] })
);
expect(message).toBe(
"MathJax Warning: Package 'undefined' not found. Omitted."
"Package 'undefined' not found. Omitted."
);
});
});
Expand All @@ -290,11 +290,11 @@ describe('MapHandler', () => {
},
});
const message = trapOutput(
'log',
'warn',
() => new TeX({ packages: ['base', 'BadHandler'] })
);
expect(message).toBe(
"TexParser Warning: Configuration 'undefindHandler' not found! Omitted."
"Configuration 'undefindHandler' not found. Omitted."
);
});

Expand Down
29 changes: 19 additions & 10 deletions testsuite/tests/util/Locale.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { describe, test, expect } from '@jest/globals';
import { trapOutput, trapAsyncOutput } from '#helpers/traps.js';
import { Locale } from '#js/util/Locale.js';
import '#js/util/asyncLoad/esm.js';

Expand Down Expand Up @@ -70,7 +71,7 @@ describe('Locale', () => {
expect(Locale.message('undefined', 'Id1')).toBe(
"MathJax(Locale): No localized or default version for message with id 'Id1' from 'undefined'"
);
expect(() => Locale.error('component', 'error', 'x')).toThrow('Error in x');
expect(() => Locale.throw('component', 'error', 'x')).toThrow('Error in x');
Locale.current = 'de';
expect(Locale.message('undefined', 'Id1')).toBe(
"MathJax(Locale): Keine lokalisierte oder Standardversion für die Meldung mit der ID 'Id1' aus 'undefined'"
Expand Down Expand Up @@ -106,17 +107,25 @@ describe('Locale', () => {
test('Locale error falls back to default locale', async () => {
const locale = Locale as any;
Locale.registerLocaleFiles('fallback', '../testsuite/lib/component');
const message = await trapAsyncOutput('error', async () => {
await locale.localeError(
'fallback',
'xy',
new Error('xy.json not found')
);
});
expect(message).toContain("MathJax(fallback): Can't load 'xy.json'");
expect(locale.data.fallback?.en).toEqual({ Id1: 'Test of %1 in %2' });
});

const errors: string[] = [];
const origError = console.error;
console.error = (msg: string) => errors.push(msg);

await locale.localeError('fallback', 'xy', new Error('xy.json not found'));

console.error = origError;
/********************************************************************************/

expect(errors[0]).toContain("MathJax(fallback): Can't load 'xy.json'");
expect(locale.data.fallback?.en).toEqual({ Id1: 'Test of %1 in %2' });
test('Locale warn', async () => {
Locale.registerLocaleFiles('component', '../testsuite/lib/component');
const message = trapOutput('warn', () =>
Locale.warn('component', 'test2', 'warn')
);
expect(message).toEqual('Has warn one');
});

/********************************************************************************/
Expand Down
19 changes: 6 additions & 13 deletions ts/input/tex/Configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ import { FunctionList } from '../../util/FunctionList.js';
import { TeX } from '../tex.js';
import { PrioritizedList } from '../../util/PrioritizedList.js';
import { TagsFactory } from './Tags.js';
export { COMPONENT } from './__locales__/Component.js';
import { Locale } from '../../util/Locale.js';
import { COMPONENT } from './__locales__/Component.js';
export { COMPONENT };

export type StackItemConfig = { [kind: string]: StackItemClass };
export type TagsConfig = { [kind: string]: TagsClass };
Expand Down Expand Up @@ -433,15 +435,15 @@ export class ParserConfiguration {
* Find a package and check that it is for the targeted parser
*
* @param {string} name The name of the package to check
* @returns {Configuration} The configuration for the package
* @returns {Configuration} The configuration for the package
*/
protected getPackage(name: string): Configuration {
const config = ConfigurationHandler.get(name);
if (config && !this.parsers.includes(config.parser)) {
throw Error(`Package '${name}' doesn't target the proper parser`);
Locale.throw(COMPONENT, 'WrongParser', name);
}
if (!config) {
this.warn(`Package '${name}' not found. Omitted.`);
Locale.warn(COMPONENT, 'PackageNotFound', name);
}
return config;
}
Expand Down Expand Up @@ -481,13 +483,4 @@ export class ParserConfiguration {
jax.postFilters.add(post, priority);
}
}

/**
* Prints a warning message.
*
* @param {string} message The warning.
*/
private warn(message: string) {
console.warn('MathJax Warning: ' + message);
}
}
Loading