Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
2 changes: 1 addition & 1 deletion src/expression/embeddedDocs/construction/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ export const indexDocs = {
'B[B>1 and B<3]'
],
seealso: [
'bignumber', 'boolean', 'complex', 'matrix,', 'number', 'range', 'string', 'unit'
'bignumber', 'boolean', 'complex', 'matrix', 'number', 'range', 'string', 'unit'
]
}
6 changes: 6 additions & 0 deletions src/expression/embeddedDocs/embeddedDocs.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ import { conjDocs } from './function/complex/conj.js'
import { imDocs } from './function/complex/im.js'
import { reDocs } from './function/complex/re.js'
import { evaluateDocs } from './function/expression/evaluate.js'
import { parserDocs } from './function/expression/parser.js'
import { parseDocs } from './function/expression/parse.js'
import { compileDocs } from './function/expression/compile.js'
import { helpDocs } from './function/expression/help.js'
import { distanceDocs } from './function/geometry/distance.js'
import { intersectDocs } from './function/geometry/intersect.js'
Expand Down Expand Up @@ -429,6 +432,9 @@ export const embeddedDocs = {
// functions - expression
evaluate: evaluateDocs,
help: helpDocs,
parse: parseDocs,
parser: parserDocs,
compile: compileDocs,

// functions - geometry
distance: distanceDocs,
Expand Down
16 changes: 16 additions & 0 deletions src/expression/embeddedDocs/function/expression/compile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const compileDocs = {
name: 'compile',
category: 'Expression',
syntax: [
'compile(expr) ',
'compile([expr1, expr2, expr3, ...])'
],
description: 'Parse and compile an expression. Returns a an object with a function evaluate([scope]) to evaluate the compiled expression.',
examples: [
'code1 = compile("sqrt(3^2 + 4^2)")',
'code1.evaluate() ',
'code2 = compile("a * b")',
'code2.evaluate({a: 3, b: 4})'
],
seealso: ['parser', 'parse', 'evaluate']
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ export const evaluateDocs = {
'evaluate("sin(x * pi)", { "x": 1/2 })',
'evaluate(["width=2", "height=4","width*height"])'
],
seealso: []
seealso: ['parser', 'parse', 'compile']
}
16 changes: 16 additions & 0 deletions src/expression/embeddedDocs/function/expression/parse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const parseDocs = {
name: 'parse',
category: 'Expression',
syntax: [
'node1 = parse(expression)',
'node1.compile().evaluate()'
],
description: 'Parse an expression. Returns a node tree, which can be evaluated by invoking node.evaluate().',
examples: [
'node1 = parse("sqrt(3^2 + 4^2)")',
'node1.compile().evaluate()',
'node2 = parse("a * b")',
'node2.compile().evaluate({a:3, b:4})'
],
seealso: ['parser', 'evaluate', 'compile']
}
20 changes: 20 additions & 0 deletions src/expression/embeddedDocs/function/expression/parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export const parserDocs = {
name: 'parser',
category: 'Expression',
syntax: [
'myParser = parser()',
'myParser.set(name, value)',
'myParser.get(name)',
'myParser.evaluate(expression)',
'myParser.evaluate([expr1, expr2, expr3, ...])'
],
description: 'Create a parser. The function creates a new math.Parser object.',
examples: [
'myParser = parser()',
'myParser.evaluate("sqrt(3^2 + 4^2)")',
'myParser.set("x", 3)',
'myParser.evaluate("y = x + 3")',
'myParser.get("y")'
],
seealso: ['evaluate', 'parse', 'compile']
}
1 change: 0 additions & 1 deletion src/expression/embeddedDocs/function/statistics/sum.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export const sumDocs = {
'min',
'prod',
'std',
'sum',
'variance'
]
}
71 changes: 70 additions & 1 deletion test/unit-tests/expression/function/help.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,52 @@ import assert from 'assert'
import math from '../../../../src/defaultInstance.js'
import { embeddedDocs } from '../../../../src/expression/embeddedDocs/embeddedDocs.js'

let mathDocs = math.create(math.all)
const originalConfig = mathDocs.config()
// Add functions to the skipDocs array if their examples in the embedded docs contain acceptable errors
const skipDocs = ['import', 'addScalar', 'divideScalar', 'equalScalar', 'multiplyScalar',
'subtractScalar', 'apply', 'replacer', 'reviver']

const testDocs = Array.from(new Set([
...Object.keys(embeddedDocs),
...Object.keys(math.expression.mathWithTransform)]))
.filter(name => !skipDocs.includes(name))

function runExamplesInDocs (name) {
mathDocs.config(originalConfig)
// every funciton should have doc.examples
const examples = mathDocs.evaluate(`help("${name}")`).doc.examples
try {
// validate if the examples run without errors
mathDocs.evaluate(examples)
return
} catch {
}
// if they still have errors try with a new math instance
mathDocs = math.create(math.all)
mathDocs.evaluate(examples)
}

function hasValidSeeAlso (name) {
let seeAlso = []
try {
seeAlso = mathDocs.evaluate(`help("${name}")`).doc.seealso
} catch (err) {
return
}
if (seeAlso && seeAlso.length > 0) {
seeAlso.forEach(see => {
if (testDocs.includes(see)) {
if (see === name) {
throw new Error(`See also name "${see}" should not be the same as "${name}" in docs for "${name}".`)
}
} else {
throw new Error(`See also with name "${see}" is not a valid documentation name used in docs for "${name}".`)
}
})
}
}

describe('help', function () {
it('should find documentation for a function by its name', function () {
const help = math.help('sin')
Expand Down Expand Up @@ -59,11 +105,34 @@ describe('help', function () {
// assert.throws(function () {math.help(undefined)}, /No documentation found/);
assert.throws(function () { math.help(new Date()) }, /No documentation found/)
assert.throws(function () { math.help('nonExistingFunction') }, /No documentation found/)
assert.throws(function () { math.help('parse') }, /No documentation found/)
assert.throws(function () { math.help('addScalar') }, /No documentation found/)
})

it('should LaTeX help', function () {
const expression = math.parse('help(parse)')
assert.strictEqual(expression.toTex(), '\\mathrm{help}\\left( parse\\right)')
})

for (const name of testDocs) {
it(`should find documentation for ${name}`, function () {
assert.doesNotThrow(() => mathDocs.help(name).doc)
})
}

for (const name of testDocs) {
it(`should find examples for ${name}`, function () {
assert.doesNotThrow(() => mathDocs.help(name).doc.examples)
})
}

for (const name of testDocs) {
it(`should run examples for ${name} without errors`, function () {
assert.doesNotThrow(() => runExamplesInDocs(name))
})
}
for (const name of testDocs) {
it(`should have all valid See Also for ${name} that are not ${name}`, function () {
assert.doesNotThrow(() => hasValidSeeAlso(name))
})
}
})