From 605bb2693b3f6610fe7752b499a653252688ab67 Mon Sep 17 00:00:00 2001 From: Duane Nykamp Date: Thu, 31 Oct 2024 21:21:31 -0500 Subject: [PATCH] convert operators tests to vitest (#252) --- .../src/components/BooleanOperators.js | 2 +- .../src/components/BooleanOperatorsOfMath.js | 6 +- .../src/components/Function.js | 65 + .../test/tagSpecific/booleanoperators.test.ts | 264 + .../booleanoperatorsonmath.test.ts | 315 ++ .../tagSpecific/functionoperators.test.ts | 3093 +++++++++++ .../e2e/tagSpecific/booleanoperators.cy.js | 714 --- .../tagSpecific/booleanoperatorsonmath.cy.js | 500 -- .../e2e/tagSpecific/functionoperators.cy.js | 4693 ----------------- 9 files changed, 3741 insertions(+), 5911 deletions(-) create mode 100644 packages/doenetml-worker/src/test/tagSpecific/booleanoperators.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/booleanoperatorsonmath.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/functionoperators.test.ts delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/booleanoperators.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/booleanoperatorsonmath.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/functionoperators.cy.js diff --git a/packages/doenetml-worker/src/components/BooleanOperators.js b/packages/doenetml-worker/src/components/BooleanOperators.js index 6ed1e0c42..2d1275f63 100644 --- a/packages/doenetml-worker/src/components/BooleanOperators.js +++ b/packages/doenetml-worker/src/components/BooleanOperators.js @@ -29,7 +29,7 @@ export class Xor extends BooleanBaseOperator { static componentType = "xor"; static applyBooleanOperator(values) { - let numberTrues = values.reduce((acc, curr) => acc + curr, 0); + let numberTrues = values.reduce((acc, curr) => acc + (curr ? 1 : 0), 0); return numberTrues === 1; } } diff --git a/packages/doenetml-worker/src/components/BooleanOperatorsOfMath.js b/packages/doenetml-worker/src/components/BooleanOperatorsOfMath.js index b6433bb45..85e198d5c 100644 --- a/packages/doenetml-worker/src/components/BooleanOperatorsOfMath.js +++ b/packages/doenetml-worker/src/components/BooleanOperatorsOfMath.js @@ -112,7 +112,9 @@ export class IsBetween extends BooleanBaseOperatorOfMath { let lim1 = dependencyValues.limits[0]; let lim2 = dependencyValues.limits[1]; - if (lim1 < lim2) { + let strict = dependencyValues.strict; + + if (lim1 < lim2 || (!strict && lim1 === lim2)) { lowerLimit = lim1; upperLimit = lim2; } else if (lim2 < lim1) { @@ -122,8 +124,6 @@ export class IsBetween extends BooleanBaseOperatorOfMath { return { setValue: { booleanOperator: () => false } }; } - let strict = dependencyValues.strict; - return { setValue: { booleanOperator: function (values) { diff --git a/packages/doenetml-worker/src/components/Function.js b/packages/doenetml-worker/src/components/Function.js index 68ec75dca..27a8f5d73 100644 --- a/packages/doenetml-worker/src/components/Function.js +++ b/packages/doenetml-worker/src/components/Function.js @@ -25,6 +25,7 @@ import { returnNVariables, roundForDisplay, mergeListsWithOtherContainers, + superSubscriptsToUnicode, } from "../utils/math"; export default class Function extends InlineComponent { @@ -2772,6 +2773,70 @@ export default class Function extends InlineComponent { }, }; + stateVariableDefinitions.text = { + public: true, + shadowingInstructions: { + createComponentOfType: "text", + }, + returnDependencies: () => ({ + functionChild: { + dependencyType: "child", + childGroups: ["functions"], + variableNames: ["text"], + }, + formula: { + dependencyType: "stateVariable", + variableName: "formula", + }, + displayDigits: { + dependencyType: "stateVariable", + variableName: "displayDigits", + }, + displayDecimals: { + dependencyType: "stateVariable", + variableName: "displayDecimals", + }, + displaySmallAsZero: { + dependencyType: "stateVariable", + variableName: "displaySmallAsZero", + }, + padZeros: { + dependencyType: "stateVariable", + variableName: "padZeros", + }, + }), + definition: function ({ dependencyValues }) { + if ( + dependencyValues.functionChild?.[0]?.componentType === + "piecewiseFunction" + ) { + // Note: A temporary solution until we can capture a piecewise function in formula (a math-expression). + // This solution is not perfect as it ignores any display attributes + // from the outer function. + return { + setValue: { + text: dependencyValues.functionChild[0].stateValues + .text, + }, + }; + } + let params = {}; + if (dependencyValues.padZeros) { + if (Number.isFinite(dependencyValues.displayDecimals)) { + params.padToDecimals = dependencyValues.displayDecimals; + } + if (dependencyValues.displayDigits >= 1) { + params.padToDigits = dependencyValues.displayDigits; + } + } + let text = roundForDisplay({ + value: dependencyValues.formula, + dependencyValues, + }).toString(params); + return { setValue: { text: superSubscriptsToUnicode(text) } }; + }, + }; + stateVariableDefinitions.functionChildrenInfoToCalculateExtrema = { returnDependencies: () => ({ functionChildren: { diff --git a/packages/doenetml-worker/src/test/tagSpecific/booleanoperators.test.ts b/packages/doenetml-worker/src/test/tagSpecific/booleanoperators.test.ts new file mode 100644 index 000000000..b5b09a673 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/booleanoperators.test.ts @@ -0,0 +1,264 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { + updateBooleanInputValue, + updateMathInputValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Boolean Operator tag tests", async () => { + it("not", async () => { + let core = await createTestCore({ + doenetML: ` + + $bi{name="bv"} + true + false + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi"].stateValues.value).eq(false); + expect(stateVariables["/bv"].stateValues.value).eq(false); + expect(stateVariables["/op1"].stateValues.value).eq(true); + expect(stateVariables["/op2"].stateValues.value).eq(false); + expect(stateVariables["/op3"].stateValues.value).eq(true); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/bi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi"].stateValues.value).eq(true); + expect(stateVariables["/bv"].stateValues.value).eq(true); + expect(stateVariables["/op1"].stateValues.value).eq(false); + }); + + it("not when", async () => { + let core = await createTestCore({ + doenetML: ` + + $mi{name="mv"} > 1 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/mi"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/mv"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/op"].stateValues.value).eq(true); + + await updateMathInputValue({ latex: "2", componentName: "/mi", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/mi"].stateValues.value.tree).eq(2); + expect(stateVariables["/mv"].stateValues.value.tree).eq(2); + expect(stateVariables["/op"].stateValues.value).eq(false); + + await updateMathInputValue({ latex: "1", componentName: "/mi", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/mi"].stateValues.value.tree).eq(1); + expect(stateVariables["/mv"].stateValues.value.tree).eq(1); + expect(stateVariables["/op"].stateValues.value).eq(true); + }); + + async function test_three_operators( + core: any, + operator: (args: boolean[]) => boolean, + ) { + async function check_items(booleans: boolean[]) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(booleans[0]); + expect(stateVariables["/bi2"].stateValues.value).eq(booleans[1]); + expect(stateVariables["/bi3"].stateValues.value).eq(booleans[2]); + expect(stateVariables["/bv1"].stateValues.value).eq(booleans[0]); + expect(stateVariables["/bv2"].stateValues.value).eq(booleans[1]); + expect(stateVariables["/bv3"].stateValues.value).eq(booleans[2]); + expect(stateVariables["/op1"].stateValues.value).eq( + operator(booleans), + ); + expect(stateVariables["/op2"].stateValues.value).eq( + operator([...booleans, true]), + ); + expect(stateVariables["/op3"].stateValues.value).eq( + operator([...booleans, false]), + ); + } + + let booleans = [false, false, false]; + + await check_items(booleans); + + booleans[0] = true; + await updateBooleanInputValue({ + boolean: booleans[0], + componentName: "/bi1", + core, + }); + await check_items(booleans); + + booleans[1] = true; + await updateBooleanInputValue({ + boolean: booleans[1], + componentName: "/bi2", + core, + }); + await check_items(booleans); + + booleans[2] = true; + await updateBooleanInputValue({ + boolean: booleans[2], + componentName: "/bi3", + core, + }); + await check_items(booleans); + } + + it("and", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $bi1 + $bi2 + $bi3 + + + $bi1 + $bi2 + $bi3 + true + + + $bi1 + $bi2 + $bi3 + false + +

+ $bi1{name="bv1"} + $bi2{name="bv2"} + $bi3{name="bv3"} +

+ `, + }); + + let andOperator = function (booleans: boolean[]) { + return booleans.reduce((a, c) => a && c, true); + }; + + await test_three_operators(core, andOperator); + }); + + it("or", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $bi1 + $bi2 + $bi3 + + + $bi1 + $bi2 + $bi3 + true + + + $bi1 + $bi2 + $bi3 + false + +

+ $bi1{name="bv1"} + $bi2{name="bv2"} + $bi3{name="bv3"} +

+ `, + }); + + let orOperator = function (booleans: boolean[]) { + return booleans.reduce((a, c) => a || c, false); + }; + + await test_three_operators(core, orOperator); + }); + + it("xor", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $bi1 + $bi2 + $bi3 + + + $bi1 + $bi2 + $bi3 + true + + + $bi1 + $bi2 + $bi3 + false + +

+ $bi1{name="bv1"} + $bi2{name="bv2"} + $bi3{name="bv3"} +

+ `, + }); + + let xorOperator = function (booleans: boolean[]) { + let numberTrues = booleans.reduce( + (acc, curr) => acc + (curr ? 1 : 0), + 0, + ); + return numberTrues === 1; + }; + + await test_three_operators(core, xorOperator); + }); + + it("show point based on logic", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + (1,2) + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi"].stateValues.value).eq(false); + expect(stateVariables["/P"].stateValues.hide).eq(true); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/bi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi"].stateValues.value).eq(true); + expect(stateVariables["/P"].stateValues.hide).eq(false); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/booleanoperatorsonmath.test.ts b/packages/doenetml-worker/src/test/tagSpecific/booleanoperatorsonmath.test.ts new file mode 100644 index 000000000..3f19e2a4d --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/booleanoperatorsonmath.test.ts @@ -0,0 +1,315 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { + updateBooleanInputValue, + updateMathInputValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Boolean Operator tag tests", async () => { + it("isinteger, is number", async () => { + let core = await createTestCore({ + doenetML: ` + + $n +

+ $n + $asNum + isinteger($n) + isinteger($asNum) + $n/2 + $asNum/2 + 5 + 5.3 + $n + $asNum + isnumber($n) + isnumber($asNum) + $n/2 + $asNum/2 + 5 + 5.3 +

+ `, + }); + + async function check_items( + isNumber: boolean, + isInteger: boolean, + isEven: boolean, + ) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/int1"].stateValues.value).eq(isInteger); + expect(stateVariables["/int2"].stateValues.value).eq(isInteger); + expect(stateVariables["/int3"].stateValues.value).eq(isInteger); + expect(stateVariables["/int4"].stateValues.value).eq(isInteger); + expect(stateVariables["/int5"].stateValues.value).eq(isEven); + expect(stateVariables["/int6"].stateValues.value).eq(isEven); + expect(stateVariables["/int7"].stateValues.value).eq(true); + expect(stateVariables["/int8"].stateValues.value).eq(false); + expect(stateVariables["/num1"].stateValues.value).eq(isNumber); + expect(stateVariables["/num2"].stateValues.value).eq(isNumber); + expect(stateVariables["/num3"].stateValues.value).eq(isNumber); + expect(stateVariables["/num4"].stateValues.value).eq(isNumber); + expect(stateVariables["/num5"].stateValues.value).eq(isNumber); + expect(stateVariables["/num6"].stateValues.value).eq(isNumber); + expect(stateVariables["/num7"].stateValues.value).eq(true); + expect(stateVariables["/num8"].stateValues.value).eq(true); + } + + let isNumber = false; + let isInteger = false; + let isEven = false; + + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ latex: "36", componentName: "/n", core }); + isNumber = true; + isInteger = true; + isEven = true; + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ latex: "37", componentName: "/n", core }); + isNumber = true; + isInteger = true; + isEven = false; + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ + latex: "37.1", + componentName: "/n", + core, + }); + isNumber = true; + isInteger = false; + isEven = false; + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ + latex: "42/3", + componentName: "/n", + core, + }); + isNumber = true; + isInteger = true; + isEven = true; + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ + latex: "-39.6/3.3", + componentName: "/n", + core, + }); + isNumber = true; + isInteger = true; + isEven = true; + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ latex: "x", componentName: "/n", core }); + isNumber = false; + isInteger = false; + isEven = false; + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ + latex: "\\sqrt{4}", + componentName: "/n", + core, + }); + isNumber = true; + isInteger = true; + isEven = true; + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ + latex: "2\\sin(\\pi/4)^2", + componentName: "/n", + core, + }); + isNumber = true; + isInteger = true; + isEven = false; + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ + latex: "1E-300", + componentName: "/n", + core, + }); + isNumber = true; + isInteger = false; + isEven = false; + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ latex: "-0", componentName: "/n", core }); + isNumber = true; + isInteger = true; + isEven = true; + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ latex: "0/0", componentName: "/n", core }); + isNumber = false; + isInteger = false; + isEven = false; + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ + latex: "10/0", + componentName: "/n", + core, + }); + isNumber = false; + isInteger = false; + isEven = false; + await check_items(isNumber, isInteger, isEven); + + await updateMathInputValue({ + latex: "10/-0", + componentName: "/n", + core, + }); + isNumber = false; + isInteger = false; + isEven = false; + await check_items(isNumber, isInteger, isEven); + }); + it("isinteger, is number", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + $x + `, + }); + + async function check_items( + x: number, + x1: number, + x2: number, + strict: boolean, + ) { + let xMin = Math.min(x1, x2); + let xMax = Math.max(x1, x2); + + let isBetween = strict + ? xMin < x && x < xMax + : xMin <= x && x <= xMax; + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ib"].stateValues.value).eq(isBetween); + } + + // non-numerical values + let x = NaN, + x1 = NaN, + x2 = NaN, + strict = false; + await check_items(x, x1, x2, strict); + + // (3,3,3,false) + x = 3; + x1 = 3; + x2 = 3; + await updateMathInputValue({ + latex: x.toString(), + componentName: "/x", + core, + }); + await updateMathInputValue({ + latex: x1.toString(), + componentName: "/x1", + core, + }); + await updateMathInputValue({ + latex: x2.toString(), + componentName: "/x2", + core, + }); + await check_items(x, x1, x2, strict); + + // (3,3,3,true) + strict = true; + await updateBooleanInputValue({ + boolean: strict, + componentName: "/strict", + core, + }); + await check_items(x, x1, x2, strict); + + // (3,3,5,true) + x2 = 5; + await updateMathInputValue({ + latex: x2.toString(), + componentName: "/x2", + core, + }); + await check_items(x, x1, x2, strict); + + // (3,3,5,false) + strict = false; + await updateBooleanInputValue({ + boolean: strict, + componentName: "/strict", + core, + }); + await check_items(x, x1, x2, strict); + + // (3,4,5,false) + x = 4; + await updateMathInputValue({ + latex: x.toString(), + componentName: "/x", + core, + }); + await check_items(x, x1, x2, strict); + + // (3,4,5,true) + strict = true; + await updateBooleanInputValue({ + boolean: strict, + componentName: "/strict", + core, + }); + await check_items(x, x1, x2, strict); + + // (3,8,5,true) + x1 = 8; + await updateMathInputValue({ + latex: x1.toString(), + componentName: "/x1", + core, + }); + await check_items(x, x1, x2, strict); + + // (7,8,5,true) + x = 7; + await updateMathInputValue({ + latex: x.toString(), + componentName: "/x", + core, + }); + await check_items(x, x1, x2, strict); + + // (7,8,8,true) + x2 = 8; + await updateMathInputValue({ + latex: x2.toString(), + componentName: "/x2", + core, + }); + await check_items(x, x1, x2, strict); + + // (7,8,8,false) + strict = false; + await updateBooleanInputValue({ + boolean: strict, + componentName: "/strict", + core, + }); + await check_items(x, x1, x2, strict); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/functionoperators.test.ts b/packages/doenetml-worker/src/test/tagSpecific/functionoperators.test.ts new file mode 100644 index 000000000..ffdec8ade --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/functionoperators.test.ts @@ -0,0 +1,3093 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { updateMathInputValue } from "../utils/actions"; +import me from "math-expressions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Function Operator tag tests", async () => { + async function test_function_operator({ + symbolic, + f1Markup, + f2Markup, + fop1, + fop2, + label1, + label2, + }: { + symbolic: boolean; + f1Markup: string; + f2Markup: string; + fop1: (arg0: number) => number; + fop2: (arg0: number) => number; + label1?: string; + label2?: string; + }) { + let core = await createTestCore({ + doenetML: ` + x^3 + ${f1Markup} + ${f2Markup} + +

+ + +

+

+ + +

+

$map1{name="map1a"}

+

$map2{name="map2a"}

+ `, + }); + + let f = (x) => x ** 3; + let f1 = (x) => fop1(f(x)); + let f2 = (x) => fop2(f(x)); + + // -2, -1.6, -1.2, ..., 2 + let xs = [...Array(11).keys()].map((v) => 0.4 * (v - 5)); + + const stateVariables = await returnAllStateVariables(core); + let map1Names: string[] = stateVariables["/map1"].replacements!.map( + (template) => + stateVariables[template.componentName].replacements![0] + .componentName, + ); + let map2Names: string[] = stateVariables["/map2"].replacements!.map( + (template) => + stateVariables[template.componentName].replacements![0] + .componentName, + ); + let map1aNames: string[] = stateVariables["/map1a"].replacements!.map( + (template) => + stateVariables[template.componentName].replacements![0] + .componentName, + ); + let map2aNames: string[] = stateVariables["/map2a"].replacements!.map( + (template) => + stateVariables[template.componentName].replacements![0] + .componentName, + ); + + let f1d = stateVariables["/f1"].stateValues.numericalfs[0]; + let f2d = stateVariables["/f2"].stateValues.numericalfs[0]; + + for (let [i, x] of xs.entries()) { + expect(stateVariables[map1Names[i]].stateValues.value.tree).closeTo( + f1(x), + 1e-10, + ); + expect(stateVariables[map2Names[i]].stateValues.value.tree).closeTo( + f2(x), + 1e-10, + ); + expect( + stateVariables[map1aNames[i]].stateValues.value.tree, + ).closeTo(f1(x), 1e-10); + expect( + stateVariables[map2aNames[i]].stateValues.value.tree, + ).closeTo(f2(x), 1e-10); + + expect(f1d(x)).closeTo(f1(x), 1e-10); + expect(f2d(x)).closeTo(f2(x), 1e-10); + } + + if (label1 !== undefined) { + expect(stateVariables["/f1"].stateValues.label).eq(label1); + } + if (label2 !== undefined) { + expect(stateVariables["/f2"].stateValues.label).eq(label2); + } + } + + it("clamp function", async () => { + await test_function_operator({ + symbolic: true, + f1Markup: `$f`, + f2Markup: `$f`, + fop1: (x) => Math.min(1, Math.max(0, x)), + fop2: (x) => Math.min(5, Math.max(-3, x)), + }); + }); + + it("clamp function, numeric, labeled", async () => { + await test_function_operator({ + symbolic: false, + f1Markup: `$f`, + f2Markup: `$f`, + fop1: (x) => Math.min(1, Math.max(0, x)), + fop2: (x) => Math.min(5, Math.max(-3, x)), + label1: "clamp 1", + label2: "clamp 2", + }); + }); + + it("wrap function", async () => { + // Note: added domain [-2,2] to reduce time spent calculating all the extrema + // when calling returnAllStateVariables() + await test_function_operator({ + symbolic: true, + f1Markup: `$f`, + f2Markup: `$f`, + fop1: (x) => me.math.mod(x, 1), + fop2: (x) => -2 + me.math.mod(x + 2, 5), + }); + }); + + it("wrap function, numeric", async () => { + // Note: added domain [-2,2] to reduce time spent calculating all the extrema + // when calling returnAllStateVariables() + await test_function_operator({ + symbolic: false, + f1Markup: `$f`, + f2Markup: `$f`, + fop1: (x) => me.math.mod(x, 1), + fop2: (x) => -2 + me.math.mod(x + 2, 5), + }); + }); + + it("derivative", async () => { + let core = await createTestCore({ + doenetML: ` +

a =

+

b =

+

c =

+

x =

+ + + $a sin($b$x + $c) + + +

f($x) = + $formula +

+ +

f'($x) = + $f +

+ + + $f + $g + + + $f + + + + + $fp + + + + + `, + }); + + async function check_items({ + a, + b, + c, + x, + x1, + x2, + }: { + a: string; + b: string; + c: string; + x: string; + x1: number; + x2: number; + }) { + // @ts-ignore + let f = me.fromText(`${a} sin(${b} ${x} + ${c})`).simplify(); + // @ts-ignore + let fp = me.fromText(`${a} ${b} cos(${b} ${x} + ${c})`).simplify(); + let fString = f.toString(); + let fpString = fp.toString(); + + let fFun0 = f.f(); + let fFunExpect = (z) => fFun0({ [x]: z }); + let fpFun0 = fp.f(); + let fpFunExpect = (z) => fpFun0({ [x]: z }); + + let y1 = fFunExpect(x1); + let y2 = fpFunExpect(x2); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pf"].stateValues.text).eq( + `f(${x}) = ${fString}`, + ); + expect(stateVariables["/pfp"].stateValues.text).eq( + `f'(${x}) = ${fpString}`, + ); + + expect(stateVariables["/f"].stateValues.formula.toString()).eq( + fString, + ); + expect(stateVariables["/fp"].stateValues.formula.toString()).eq( + fpString, + ); + + expect(stateVariables["/P1"].stateValues.xs[0].tree).closeTo( + x1, + 1e-12, + ); + expect(stateVariables["/P1"].stateValues.xs[1].tree).closeTo( + y1, + 1e-12, + ); + expect(stateVariables["/P2"].stateValues.xs[0].tree).closeTo( + x2, + 1e-12, + ); + expect(stateVariables["/P2"].stateValues.xs[1].tree).closeTo( + y2, + 1e-12, + ); + + let fFun = stateVariables["/f"].stateValues.numericalfs[0]; + let fpFun = stateVariables["/fp"].stateValues.numericalfs[0]; + + for (let i = 1; i <= 21; i++) { + let x = 0.2 * (i - 11); + expect(fFun(x)).closeTo(fFunExpect(x), 1e-10); + expect(fpFun(x)).closeTo(fpFunExpect(x), 1e-10); + } + } + + let a = "1", + b = "1", + c = "1", + x = "x", + x1 = 3, + x2 = 3; + + await check_items({ a, b, c, x, x1, x2 }); + + x1 = -3; + x2 = 5; + + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/P1", + args: { x: x1, y: 11 }, + }); + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/P2", + args: { x: x2, y: -9 }, + }); + + await check_items({ a, b, c, x, x1, x2 }); + + a = "2"; + b = "pi"; + c = "e"; + x = "q"; + + await updateMathInputValue({ latex: a, componentName: "/a", core }); + await updateMathInputValue({ + latex: "\\pi", + componentName: "/b", + core, + }); + await updateMathInputValue({ latex: c, componentName: "/c", core }); + await updateMathInputValue({ latex: x, componentName: "/x", core }); + + await check_items({ a, b, c, x, x1, x2 }); + + x1 = 9; + x2 = -7; + + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/P1", + args: { x: x1, y: -6 }, + }); + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/P2", + args: { x: x2, y: 0 }, + }); + + await check_items({ a, b, c, x, x1, x2 }); + }); + + async function checkd_list(core: any) { + const stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/d1"].stateValues.formula.equals(me.fromText("2x")), + ).eq(true); + expect( + stateVariables["/d2"].stateValues.formula.equals(me.fromText("2x")), + ).eq(true); + expect( + stateVariables["/d2b"].stateValues.formula.equals( + me.fromText("2x"), + ), + ).eq(true); + expect( + stateVariables["/d2c"].stateValues.formula.equals( + me.fromText("2x"), + ), + ).eq(true); + expect( + stateVariables["/d3"].stateValues.formula.equals( + me.fromText("2x sin(z)"), + ), + ).eq(true); + expect( + stateVariables["/d4"].stateValues.formula.equals( + me.fromText("x^2cos(z)"), + ), + ).eq(true); + expect( + stateVariables["/d4b"].stateValues.formula.equals( + me.fromText("x^2cos(z)"), + ), + ).eq(true); + expect( + stateVariables["/d5"].stateValues.formula.equals( + me.fromText("cos(x)"), + ), + ).eq(true); + expect( + stateVariables["/d5b"].stateValues.formula.equals( + me.fromText("cos(x)"), + ), + ).eq(true); + expect( + stateVariables["/d6"].stateValues.formula.equals( + me.fromText("2e^(2y)"), + ), + ).eq(true); + expect( + stateVariables["/d6b"].stateValues.formula.equals( + me.fromText("2e^(2y)"), + ), + ).eq(true); + expect( + stateVariables["/d7"].stateValues.formula.equals(me.fromText("yz")), + ).eq(true); + expect( + stateVariables["/d7b"].stateValues.formula.equals( + me.fromText("yz"), + ), + ).eq(true); + expect( + stateVariables["/d8"].stateValues.formula.equals(me.fromText("xy")), + ).eq(true); + expect( + stateVariables["/d8b"].stateValues.formula.equals( + me.fromText("xy"), + ), + ).eq(true); + expect( + stateVariables["/d9"].stateValues.formula.equals(me.fromText("0")), + ).eq(true); + expect( + stateVariables["/d10"].stateValues.formula.equals(me.fromText("0")), + ).eq(true); + expect( + stateVariables["/d11"].stateValues.formula.equals(me.fromText("0")), + ).eq(true); + expect( + stateVariables["/d12"].stateValues.formula.equals(me.fromText("0")), + ).eq(true); + expect( + stateVariables["/d13"].stateValues.formula.equals( + me.fromText("xz"), + ), + ).eq(true); + expect( + stateVariables["/d14"].stateValues.formula.equals( + me.fromText("xz"), + ), + ).eq(true); + + const d1 = stateVariables["/d1"].stateValues.numericalfs[0]; + const d2 = stateVariables["/d2"].stateValues.numericalfs[0]; + const d2b = stateVariables["/d2b"].stateValues.numericalfs[0]; + const d2c = stateVariables["/d2c"].stateValues.numericalfs[0]; + const d5 = stateVariables["/d5"].stateValues.numericalfs[0]; + const d5b = stateVariables["/d5b"].stateValues.numericalfs[0]; + const d6 = stateVariables["/d6"].stateValues.numericalfs[0]; + const d6b = stateVariables["/d6b"].stateValues.numericalfs[0]; + const d9 = stateVariables["/d9"].stateValues.numericalfs[0]; + const d10 = stateVariables["/d10"].stateValues.numericalfs[0]; + const d11 = stateVariables["/d11"].stateValues.numericalfs[0]; + const d12 = stateVariables["/d12"].stateValues.numericalfs[0]; + + for (let i = 1; i <= 21; i++) { + let x = 0.2 * (i - 11); + expect(d1(x)).closeTo(2 * x, 1e-10); + expect(d2(x)).closeTo(2 * x, 1e-10); + expect(d2b(x)).closeTo(2 * x, 1e-10); + expect(d2c(x)).closeTo(2 * x, 1e-10); + expect(d5(x)).closeTo(Math.cos(x), 1e-10); + expect(d5b(x)).closeTo(Math.cos(x), 1e-10); + expect(d6(x)).closeTo(2 * Math.exp(2 * x), 1e-10); + expect(d6b(x)).closeTo(2 * Math.exp(2 * x), 1e-10); + expect(d9(x)).closeTo(0, 1e-10); + expect(d10(x)).closeTo(0, 1e-10); + expect(d11(x)).closeTo(0, 1e-10); + expect(d12(x)).closeTo(0, 1e-10); + } + } + it("derivative 2", async () => { + let core = await createTestCore({ + doenetML: ` + sin(x) + e^(2y) + xyz + xyz + x^2 + x^2 + $x2 + $x2 + x^2sin(z) + x^2sin(z) + z2 + x^$a sin($var) + $f1 + $f1 + $f2 + $f2 + $f3 + $f3 + $f4 + $f4 + $f1 + $f2 + $f3 + $f4 + $f3 + $f4 + `, + }); + + await checkd_list(core); + }); + + it("derivative 2, labeled", async () => { + let core = await createTestCore({ + doenetML: ` + sin(x) + e^(2y) + xyz + xyz + x^2 + x^2 + $x2 + $x2 + x^2sin(z) + x^2sin(z) + z2 + x^$a sin($var) + $f1 + $f1 + $f2 + $f2 + $f3 + $f3 + $f4 + $f4 + $f1 + $f2 + $f3 + $f4 + $f3 + $f4 + `, + }); + + await checkd_list(core); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/d1"].stateValues.label).eq("d1"); + expect(stateVariables["/d2"].stateValues.label).eq("d2"); + expect(stateVariables["/d2b"].stateValues.label).eq("d2b"); + expect(stateVariables["/d2c"].stateValues.label).eq("d2c"); + expect(stateVariables["/d3"].stateValues.label).eq("d3"); + expect(stateVariables["/d4"].stateValues.label).eq("d4"); + expect(stateVariables["/d4b"].stateValues.label).eq("d4b"); + expect(stateVariables["/d5"].stateValues.label).eq("d5"); + expect(stateVariables["/d5b"].stateValues.label).eq("d5b"); + expect(stateVariables["/d6"].stateValues.label).eq("d6"); + expect(stateVariables["/d6b"].stateValues.label).eq("d6b"); + expect(stateVariables["/d7"].stateValues.label).eq("d7"); + expect(stateVariables["/d7b"].stateValues.label).eq("d7b"); + expect(stateVariables["/d8"].stateValues.label).eq("d8"); + expect(stateVariables["/d8b"].stateValues.label).eq("d8b"); + expect(stateVariables["/d9"].stateValues.label).eq("d9"); + expect(stateVariables["/d10"].stateValues.label).eq("d10"); + expect(stateVariables["/d11"].stateValues.label).eq("d11"); + expect(stateVariables["/d12"].stateValues.label).eq("d12"); + expect(stateVariables["/d13"].stateValues.label).eq("d13"); + expect(stateVariables["/d14"].stateValues.label).eq("d14"); + }); + + it("specifying derivative variables of a function", async () => { + let core = await createTestCore({ + doenetML: ` +

sin(x+y^2)z + sin(x+y^2)z + sin(x+y^2)z + sin(x_1+x_2^2)x_3

+ +

$f1 + $f1 + $f1 + $f1 + $f1 + $f1 + $f1 + $f1

+ +

$f2 + $f2 + $f2 + $f2 + $f2 + $f2 + $f2 + $f2

+ +

$f3 + $f3 + $f3 + $f3 + $f3 + $f3 + $f3 + $f3

+ +

$f4 + $f4 + $f4 + $f4

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/d11"].stateValues.formula.equals( + me.fromText("cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d11"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d11"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d12"].stateValues.formula.equals( + me.fromText("sin(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d12"].stateValues.variables.map((x) => x.tree), + ).eqls(["z"]); + expect( + stateVariables["/d12"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/d13"].stateValues.formula.equals( + me.fromText("cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d13"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d13"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d14"].stateValues.formula.equals( + me.fromText("sin(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d14"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d14"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/d15"].stateValues.formula.equals( + me.fromText("2 y cos(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d15"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d15"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["y", "z"]); + + expect( + stateVariables["/d16"].stateValues.formula.equals( + me.fromText("-2 y cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d16"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d16"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x", "x", "y"]); + + expect( + stateVariables["/d17"].stateValues.formula.equals(me.fromText("0")), + ).eq(true); + expect( + stateVariables["/d17"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d17"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["u"]); + + expect( + stateVariables["/d18"].stateValues.formula.equals( + me.fromText("-2 y cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d18"].stateValues.variables.map((x) => x.tree), + ).eqls(["z"]); + expect( + stateVariables["/d18"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x", "x", "y"]); + + expect( + stateVariables["/d21"].stateValues.formula.equals( + me.fromText("sin(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d21"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y", "x"]); + expect( + stateVariables["/d21"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/d22"].stateValues.formula.equals( + me.fromText("cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d22"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + expect( + stateVariables["/d22"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d23"].stateValues.formula.equals( + me.fromText("cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d23"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y", "x"]); + expect( + stateVariables["/d23"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d24"].stateValues.formula.equals( + me.fromText("sin(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d24"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y", "x"]); + expect( + stateVariables["/d24"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/d25"].stateValues.formula.equals( + me.fromText("2 y cos(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d25"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y", "x"]); + expect( + stateVariables["/d25"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["y", "z"]); + + expect( + stateVariables["/d26"].stateValues.formula.equals( + me.fromText("-2 y cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d26"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y", "x"]); + expect( + stateVariables["/d26"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x", "x", "y"]); + + expect( + stateVariables["/d27"].stateValues.formula.equals(me.fromText("0")), + ).eq(true); + expect( + stateVariables["/d27"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y", "x"]); + expect( + stateVariables["/d27"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["u"]); + + expect( + stateVariables["/d28"].stateValues.formula.equals( + me.fromText("-2 y cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d28"].stateValues.variables.map((x) => x.tree), + ).eqls(["z"]); + expect( + stateVariables["/d28"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x", "x", "y"]); + + expect( + stateVariables["/d31"].stateValues.formula.equals( + me.fromText("cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d31"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y"]); + expect( + stateVariables["/d31"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d32"].stateValues.formula.equals( + me.fromText("sin(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d32"].stateValues.variables.map((x) => x.tree), + ).eqls(["z"]); + expect( + stateVariables["/d32"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/d33"].stateValues.formula.equals( + me.fromText("cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d33"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y"]); + expect( + stateVariables["/d33"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d34"].stateValues.formula.equals( + me.fromText("sin(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d34"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y"]); + expect( + stateVariables["/d34"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/d35"].stateValues.formula.equals( + me.fromText("2 y cos(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d35"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y"]); + expect( + stateVariables["/d35"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["y", "z"]); + + expect( + stateVariables["/d36"].stateValues.formula.equals( + me.fromText("-2 y cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d36"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y"]); + expect( + stateVariables["/d36"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x", "x", "y"]); + + expect( + stateVariables["/d37"].stateValues.formula.equals(me.fromText("0")), + ).eq(true); + expect( + stateVariables["/d37"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y"]); + expect( + stateVariables["/d37"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["u"]); + + expect( + stateVariables["/d38"].stateValues.formula.equals( + me.fromText("-2 y cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d38"].stateValues.variables.map((x) => x.tree), + ).eqls(["z"]); + expect( + stateVariables["/d38"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x", "x", "y"]); + + expect( + stateVariables["/d41"].stateValues.formula.equals( + me.fromText("cos(x_1+x_2^2)x_3"), + ), + ).eq(true); + expect( + stateVariables["/d41"].stateValues.variables.map((x) => x.tree), + ).eqls([ + ["_", "x", 1], + ["_", "x", 2], + ["_", "x", 3], + ]); + expect( + stateVariables["/d41"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls([["_", "x", 1]]); + + expect( + stateVariables["/d42"].stateValues.formula.equals( + me.fromText("-2 x_2 sin(x_1+x_2^2)"), + ), + ).eq(true); + expect( + stateVariables["/d42"].stateValues.variables.map((x) => x.tree), + ).eqls([ + ["_", "x", 1], + ["_", "x", 2], + ["_", "x", 3], + ]); + expect( + stateVariables["/d42"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls([ + ["_", "x", 1], + ["_", "x", 2], + ["_", "x", 3], + ]); + + expect( + stateVariables["/d43"].stateValues.formula.equals(me.fromText("0")), + ).eq(true); + expect( + stateVariables["/d43"].stateValues.variables.map((x) => x.tree), + ).eqls([ + ["_", "x", 1], + ["_", "x", 2], + ["_", "x", 3], + ]); + expect( + stateVariables["/d43"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d44"].stateValues.formula.equals( + me.fromText("-2 x_2 sin(x_1+x_2^2)"), + ), + ).eq(true); + expect( + stateVariables["/d44"].stateValues.variables.map((x) => x.tree), + ).eqls([ + ["_", "x", 3], + ["_", "x", 2], + ["_", "x", 1], + ]); + expect( + stateVariables["/d44"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls([ + ["_", "x", 1], + ["_", "x", 2], + ["_", "x", 3], + ]); + }); + + it("specifying derivative variables of an expression", async () => { + let core = await createTestCore({ + doenetML: ` + sin(x+y^2)z + sin(x_1+x_2^2)x_3 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + $m1 + + + $m2 + $m2 + $m2 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/d1"].stateValues.formula.equals( + me.fromText("cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d1"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + expect( + stateVariables["/d1"].stateValues.derivVariables.map((x) => x.tree), + ).eqls(["x"]); + + expect( + stateVariables["/d2"].stateValues.formula.equals( + me.fromText("cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d2"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + expect( + stateVariables["/d2"].stateValues.derivVariables.map((x) => x.tree), + ).eqls(["x"]); + + expect( + stateVariables["/d3"].stateValues.formula.equals( + me.fromText("cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d3"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d3"].stateValues.derivVariables.map((x) => x.tree), + ).eqls(["x"]); + + expect( + stateVariables["/d4"].stateValues.formula.equals( + me.fromText("sin(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d4"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y", "x"]); + expect( + stateVariables["/d4"].stateValues.derivVariables.map((x) => x.tree), + ).eqls(["z"]); + + expect( + stateVariables["/d5"].stateValues.formula.equals( + me.fromText("cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d5"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + expect( + stateVariables["/d5"].stateValues.derivVariables.map((x) => x.tree), + ).eqls(["x"]); + + expect( + stateVariables["/d5a"].stateValues.formula.equals( + me.fromText("cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d5a"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d5a"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d6"].stateValues.formula.equals( + me.fromText("-sin(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d6"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + expect( + stateVariables["/d6"].stateValues.derivVariables.map((x) => x.tree), + ).eqls(["x", "x"]); + + expect( + stateVariables["/d6a"].stateValues.formula.equals( + me.fromText("-sin(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d6a"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + expect( + stateVariables["/d6a"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d6b"].stateValues.formula.equals( + me.fromText("-sin(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d6b"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d6b"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d6c"].stateValues.formula.equals( + me.fromText("-sin(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d6c"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d6c"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d6d"].stateValues.formula.equals( + me.fromText("-sin(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d6d"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d6d"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x", "x"]); + + expect( + stateVariables["/d7"].stateValues.formula.equals( + me.fromText("-2 y sin(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d7"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y"]); + expect( + stateVariables["/d7"].stateValues.derivVariables.map((x) => x.tree), + ).eqls(["x", "y"]); + + expect( + stateVariables["/d7a"].stateValues.formula.equals( + me.fromText("-2 y sin(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d7a"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + expect( + stateVariables["/d7a"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["y"]); + + expect( + stateVariables["/d7b"].stateValues.formula.equals( + me.fromText("-2 y sin(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d7b"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d7b"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["y"]); + + expect( + stateVariables["/d7c"].stateValues.formula.equals( + me.fromText("-2 y sin(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d7c"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d7c"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["y"]); + + expect( + stateVariables["/d8"].stateValues.formula.equals( + me.fromText("-2 y sin(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d8"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d8"].stateValues.derivVariables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + + expect( + stateVariables["/d8a"].stateValues.formula.equals( + me.fromText("-2 y sin(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d8a"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + expect( + stateVariables["/d8a"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/d8b"].stateValues.formula.equals( + me.fromText("-2 y sin(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d8b"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d8b"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/d8c"].stateValues.formula.equals( + me.fromText("-2 y sin(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d8c"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d8c"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/d9"].stateValues.formula.equals( + me.fromText("-2 y cos(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d9"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d9"].stateValues.derivVariables.map((x) => x.tree), + ).eqls(["x", "y", "z", "x"]); + + expect( + stateVariables["/d9a"].stateValues.formula.equals( + me.fromText("-2 y cos(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d9a"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + expect( + stateVariables["/d9a"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d9b"].stateValues.formula.equals( + me.fromText("-2 y cos(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d9b"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d9b"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d9c"].stateValues.formula.equals( + me.fromText("-2 y cos(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/d9c"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d9c"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/d10"].stateValues.formula.equals(me.fromText("0")), + ).eq(true); + expect( + stateVariables["/d10"].stateValues.variables.map((x) => x.tree), + ).eqls(["q"]); + expect( + stateVariables["/d10"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["q"]); + + expect( + stateVariables["/d11"].stateValues.formula.equals( + me.fromText("2 y cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d11"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/d11"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["y"]); + + expect( + stateVariables["/d12"].stateValues.formula.equals( + me.fromText("2 y cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/d12"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "z"]); + expect( + stateVariables["/d12"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["y"]); + + expect( + stateVariables["/d13"].stateValues.formula.equals( + me.fromText("cos(x_1+x_2^2)x_3"), + ), + ).eq(true); + expect( + stateVariables["/d13"].stateValues.variables.map((x) => x.tree), + ).eqls([ + ["_", "x", 1], + ["_", "x", 2], + ["_", "x", 3], + ]); + expect( + stateVariables["/d13"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls([["_", "x", 1]]); + + expect( + stateVariables["/d14"].stateValues.formula.equals( + me.fromText("-sin(x_1+x_2^2)x_3"), + ), + ).eq(true); + expect( + stateVariables["/d14"].stateValues.variables.map((x) => x.tree), + ).eqls([["_", "x", 1]]); + expect( + stateVariables["/d14"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls([ + ["_", "x", 1], + ["_", "x", 1], + ]); + + expect( + stateVariables["/d15"].stateValues.formula.equals( + me.fromText("-sin(x_1+x_2^2)x_3"), + ), + ).eq(true); + expect( + stateVariables["/d15"].stateValues.variables.map((x) => x.tree), + ).eqls([ + ["_", "x", 1], + ["_", "x", 2], + ["_", "x", 3], + ]); + expect( + stateVariables["/d15"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls([ + ["_", "x", 1], + ["_", "x", 1], + ]); + }); + + it("derivative of function with changed variables", async () => { + let core = await createTestCore({ + doenetML: ` + sin(x+y^2)z + $f1 + sin(x_1+x_2^2)x_3 + $g1 + $f1 + $df1 + $f2 + $df2 + $g1 + $dg1 + $g2 + $dg2 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/df1"].stateValues.formula.equals( + me.fromText("cos(x+y^2)z"), + ), + ).eq(true); + expect( + stateVariables["/df1"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/df1"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + expect( + stateVariables["/df2"].stateValues.formula.equals( + me.fromText("sin(x+y^2)"), + ), + ).eq(true); + expect( + stateVariables["/df2"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y", "x"]); + expect( + stateVariables["/df2"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/dg1"].stateValues.formula.equals( + me.fromText("cos(x_1+x_2^2)x_3"), + ), + ).eq(true); + expect( + stateVariables["/dg1"].stateValues.variables.map((x) => x.tree), + ).eqls([ + ["_", "x", 1], + ["_", "x", 2], + ["_", "x", 3], + ]); + expect( + stateVariables["/dg1"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls([["_", "x", 1]]); + + expect( + stateVariables["/dg2"].stateValues.formula.equals( + me.fromText("sin(x_1+x_2^2)"), + ), + ).eq(true); + expect( + stateVariables["/dg2"].stateValues.variables.map((x) => x.tree), + ).eqls([ + ["_", "x", 3], + ["_", "x", 2], + ["_", "x", 1], + ]); + expect( + stateVariables["/dg2"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls([["_", "x", 3]]); + }); + + it("derivative of function with changed variables, convert to single variable function", async () => { + let core = await createTestCore({ + doenetML: ` + sin(x)z + $f1.formula + sin(x)yz + $f3.formula + + $f1 + $f2 + $df2.formula + $f3 + $f3 + $df3y + $f4 + $f4 + $df4z + $df4zy.formula + $df4yz.formula + + + $df2a + + + + $df4zya + + + + $df4yza + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/df1"].stateValues.formula.equals( + me.fromText("sin(x)"), + ), + ).eq(true); + expect( + stateVariables["/df1"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/df1"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/df2"].stateValues.formula.equals( + me.fromText("sin(x)"), + ), + ).eq(true); + expect( + stateVariables["/df2"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y", "x"]); + expect( + stateVariables["/df2"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/df2a"].stateValues.formula.equals( + me.fromText("sin(x)"), + ), + ).eq(true); + expect( + stateVariables["/df2a"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + + expect( + stateVariables["/df3zy"].stateValues.formula.equals( + me.fromText("sin(x)"), + ), + ).eq(true); + expect( + stateVariables["/df3zy"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/df3zy"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z", "y"]); + + expect( + stateVariables["/df3y"].stateValues.formula.equals( + me.fromText("sin(x)z"), + ), + ).eq(true); + expect( + stateVariables["/df3y"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/df3y"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["y"]); + + expect( + stateVariables["/df3zya"].stateValues.formula.equals( + me.fromText("sin(x)"), + ), + ).eq(true); + expect( + stateVariables["/df3zya"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/df3zya"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/df4zy"].stateValues.formula.equals( + me.fromText("sin(x)"), + ), + ).eq(true); + expect( + stateVariables["/df4zy"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y", "x"]); + expect( + stateVariables["/df4zy"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z", "y"]); + + expect( + stateVariables["/df4z"].stateValues.formula.equals( + me.fromText("sin(x)y"), + ), + ).eq(true); + expect( + stateVariables["/df4z"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y", "x"]); + expect( + stateVariables["/df4z"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["z"]); + + expect( + stateVariables["/df4yz"].stateValues.formula.equals( + me.fromText("sin(x)"), + ), + ).eq(true); + expect( + stateVariables["/df4yz"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y", "x"]); + expect( + stateVariables["/df4yz"].stateValues.derivVariables.map( + (x) => x.tree, + ), + ).eqls(["y"]); + + expect( + stateVariables["/df4zya"].stateValues.formula.equals( + me.fromText("sin(x)"), + ), + ).eq(true); + expect( + stateVariables["/df4zya"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + + expect( + stateVariables["/df4yza"].stateValues.formula.equals( + me.fromText("sin(x)"), + ), + ).eq(true); + expect( + stateVariables["/df4yza"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + + expect(stateVariables["/t1/df1"].stateValues.value.tree).eqls([ + "apply", + "sin", + -2, + ]); + expect(stateVariables["/t1/df2a"].stateValues.value.tree).eqls([ + "apply", + "sin", + -2, + ]); + expect(stateVariables["/t1/df3zy"].stateValues.value.tree).eqls([ + "apply", + "sin", + -2, + ]); + expect(stateVariables["/t1/df3zya"].stateValues.value.tree).eqls([ + "apply", + "sin", + -2, + ]); + expect(stateVariables["/t1/df4zya"].stateValues.value.tree).eqls([ + "apply", + "sin", + -2, + ]); + expect(stateVariables["/t1/df4yza"].stateValues.value.tree).eqls([ + "apply", + "sin", + -2, + ]); + expect(stateVariables["/t1/df1n"].stateValues.value.tree).closeTo( + Math.sin(-2), + 1e-10, + ); + expect(stateVariables["/t1/df2an"].stateValues.value.tree).closeTo( + Math.sin(-2), + 1e-10, + ); + expect(stateVariables["/t1/df3zyn"].stateValues.value.tree).closeTo( + Math.sin(-2), + 1e-10, + ); + expect(stateVariables["/t1/df3zyan"].stateValues.value.tree).closeTo( + Math.sin(-2), + 1e-10, + ); + expect(stateVariables["/t1/df4zyan"].stateValues.value.tree).closeTo( + Math.sin(-2), + 1e-10, + ); + expect(stateVariables["/t1/df4yzan"].stateValues.value.tree).closeTo( + Math.sin(-2), + 1e-10, + ); + + expect(stateVariables["/t2/df1"].stateValues.value.tree).eq(0); + expect(stateVariables["/t2/df2a"].stateValues.value.tree).eq(0); + expect(stateVariables["/t2/df3zy"].stateValues.value.tree).eq(0); + expect(stateVariables["/t2/df3zya"].stateValues.value.tree).eq(0); + expect(stateVariables["/t2/df4zya"].stateValues.value.tree).eq(0); + expect(stateVariables["/t2/df4yza"].stateValues.value.tree).eq(0); + expect(stateVariables["/t2/df1n"].stateValues.value.tree).closeTo( + 0, + 1e-10, + ); + expect(stateVariables["/t2/df2an"].stateValues.value.tree).closeTo( + 0, + 1e-10, + ); + expect(stateVariables["/t2/df3zyn"].stateValues.value.tree).closeTo( + 0, + 1e-10, + ); + expect(stateVariables["/t2/df3zyan"].stateValues.value.tree).closeTo( + 0, + 1e-10, + ); + expect(stateVariables["/t2/df4zyan"].stateValues.value.tree).closeTo( + 0, + 1e-10, + ); + expect(stateVariables["/t2/df4yzan"].stateValues.value.tree).closeTo( + 0, + 1e-10, + ); + + expect(stateVariables["/t3/df1"].stateValues.value.tree).eqls([ + "apply", + "sin", + 2, + ]); + expect(stateVariables["/t3/df2a"].stateValues.value.tree).eqls([ + "apply", + "sin", + 2, + ]); + expect(stateVariables["/t3/df3zy"].stateValues.value.tree).eqls([ + "apply", + "sin", + 2, + ]); + expect(stateVariables["/t3/df3zya"].stateValues.value.tree).eqls([ + "apply", + "sin", + 2, + ]); + expect(stateVariables["/t3/df4zya"].stateValues.value.tree).eqls([ + "apply", + "sin", + 2, + ]); + expect(stateVariables["/t3/df4yza"].stateValues.value.tree).eqls([ + "apply", + "sin", + 2, + ]); + expect(stateVariables["/t3/df1n"].stateValues.value.tree).closeTo( + Math.sin(2), + 1e-10, + ); + expect(stateVariables["/t3/df2an"].stateValues.value.tree).closeTo( + Math.sin(2), + 1e-10, + ); + expect(stateVariables["/t3/df3zyn"].stateValues.value.tree).closeTo( + Math.sin(2), + 1e-10, + ); + expect(stateVariables["/t3/df3zyan"].stateValues.value.tree).closeTo( + Math.sin(2), + 1e-10, + ); + expect(stateVariables["/t3/df4zyan"].stateValues.value.tree).closeTo( + Math.sin(2), + 1e-10, + ); + expect(stateVariables["/t3/df4yzan"].stateValues.value.tree).closeTo( + Math.sin(2), + 1e-10, + ); + + let df1 = stateVariables["/df1"].stateValues.numericalfs[0]; + let df2a = stateVariables["/df2a"].stateValues.numericalfs[0]; + let df3zy = stateVariables["/df3zy"].stateValues.numericalfs[0]; + let df3zya = stateVariables["/df3zya"].stateValues.numericalfs[0]; + let df4zya = stateVariables["/df4zya"].stateValues.numericalfs[0]; + let df4yza = stateVariables["/df4yza"].stateValues.numericalfs[0]; + + for (let i = 1; i <= 21; i++) { + let x = 0.2 * (i - 11); + expect(df1(x, 0, 0)).closeTo(Math.sin(x), 1e-10); + expect(df2a(x)).closeTo(Math.sin(x), 1e-10); + expect(df3zy(x, 0, 0)).closeTo(Math.sin(x), 1e-10); + expect(df3zya(x, 0, 0)).closeTo(Math.sin(x), 1e-10); + expect(df4zya(x)).closeTo(Math.sin(x), 1e-10); + expect(df4yza(x)).closeTo(Math.sin(x), 1e-10); + } + }); + + it("derivative with empty variables attribute", async () => { + let core = await createTestCore({ + doenetML: ` + x^2 + + + $d1 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/d1"].stateValues.formula.equals(me.fromText("2x")), + ).eq(true); + expect( + stateVariables["/d1"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + expect( + stateVariables["/d1"].stateValues.derivVariables.map((x) => x.tree), + ).eqls(["x"]); + + let d1 = stateVariables["/d1"].stateValues.numericalfs[0]; + + for (let i = 1; i <= 21; i++) { + let x = 0.2 * (i - 11); + expect(d1(x)).closeTo(2 * x, 1e-10); + } + }); + + it("derivatives of vector-valued functions", async () => { + let core = await createTestCore({ + doenetML: ` + (sin(x), cos(x)) + (e^(2y), y, log(y)) + (xyz, xy, xz, yz) + (xyz, xy, xz, yz) + (x^2, x^3) + (x^2, x^3) + $x2 + $x2 + (x^2sin(z), z^2sin(x)) + (x^2sin(z),z^2sin(x)) + z2 + (x^$a sin($var), $var^$a sin(x)) + $f1 + $f1 + $f2 + $f2 + $f3 + $f3 + $f4 + $f4 + $f1 + $f2 + $f3 + $f4 + $f3 + $f4 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/d1"].stateValues.formula.equals( + me.fromText("(2x,3x^2)"), + ), + ).eq(true); + expect( + stateVariables["/d2"].stateValues.formula.equals( + me.fromText("(2x,3x^2)"), + ), + ).eq(true); + expect( + stateVariables["/d2b"].stateValues.formula.equals( + me.fromText("(2x,3x^2)"), + ), + ).eq(true); + expect( + stateVariables["/d2c"].stateValues.formula.equals( + me.fromText("(2x,3x^2)"), + ), + ).eq(true); + expect( + stateVariables["/d3"].stateValues.formula.equals( + me.fromText("(2x sin(z), z^2 cos(x))"), + ), + ).eq(true); + expect( + stateVariables["/d4"].stateValues.formula.equals( + me.fromText("(x^2cos(z), 2z sin(x))"), + ), + ).eq(true); + expect( + stateVariables["/d4b"].stateValues.formula.equals( + me.fromText("(x^2cos(z), 2z sin(x))"), + ), + ).eq(true); + expect( + stateVariables["/d5"].stateValues.formula.equals( + me.fromText("(cos(x),-sin(x))"), + ), + ).eq(true); + expect( + stateVariables["/d5b"].stateValues.formula.equals( + me.fromText("(cos(x), -sin(x))"), + ), + ).eq(true); + expect( + stateVariables["/d6"].stateValues.formula.equals( + me.fromText("(2e^(2y),1,1/y)"), + ), + ).eq(true); + expect( + stateVariables["/d6b"].stateValues.formula.equals( + me.fromText("(2e^(2y),1,1/y)"), + ), + ).eq(true); + expect( + stateVariables["/d7"].stateValues.formula.equals( + me.fromText("(yz, y, z, 0)"), + ), + ).eq(true); + expect( + stateVariables["/d7b"].stateValues.formula.equals( + me.fromText("(yz, y, z, 0)"), + ), + ).eq(true); + expect( + stateVariables["/d8"].stateValues.formula.equals( + me.fromText("(xy, 0, x, y)"), + ), + ).eq(true); + expect( + stateVariables["/d8b"].stateValues.formula.equals( + me.fromText("(xy, 0, x, y)"), + ), + ).eq(true); + expect( + stateVariables["/d9"].stateValues.formula.equals( + me.fromText("(0,0)"), + ), + ).eq(true); + expect( + stateVariables["/d10"].stateValues.formula.equals( + me.fromText("(0,0,0)"), + ), + ).eq(true); + expect( + stateVariables["/d11"].stateValues.formula.equals( + me.fromText("(0,0,0,0)"), + ), + ).eq(true); + expect( + stateVariables["/d12"].stateValues.formula.equals( + me.fromText("(0,0,0,0)"), + ), + ).eq(true); + expect( + stateVariables["/d13"].stateValues.formula.equals( + me.fromText("(xz,x,0,z)"), + ), + ).eq(true); + expect( + stateVariables["/d14"].stateValues.formula.equals( + me.fromText("(xz,x,0,z)"), + ), + ).eq(true); + + let d1_1 = stateVariables["/d1"].stateValues.numericalfs[0]; + let d1_2 = stateVariables["/d1"].stateValues.numericalfs[1]; + let d2_1 = stateVariables["/d2"].stateValues.numericalfs[0]; + let d2_2 = stateVariables["/d2"].stateValues.numericalfs[1]; + let d2b_1 = stateVariables["/d2b"].stateValues.numericalfs[0]; + let d2b_2 = stateVariables["/d2b"].stateValues.numericalfs[1]; + let d2c_1 = stateVariables["/d2c"].stateValues.numericalfs[0]; + let d2c_2 = stateVariables["/d2c"].stateValues.numericalfs[1]; + let d5_1 = stateVariables["/d5"].stateValues.numericalfs[0]; + let d5_2 = stateVariables["/d5"].stateValues.numericalfs[1]; + let d5b_1 = stateVariables["/d5b"].stateValues.numericalfs[0]; + let d5b_2 = stateVariables["/d5b"].stateValues.numericalfs[1]; + let d6_1 = stateVariables["/d6"].stateValues.numericalfs[0]; + let d6_2 = stateVariables["/d6"].stateValues.numericalfs[1]; + let d6_3 = stateVariables["/d6"].stateValues.numericalfs[2]; + let d6b_1 = stateVariables["/d6b"].stateValues.numericalfs[0]; + let d6b_2 = stateVariables["/d6b"].stateValues.numericalfs[1]; + let d6b_3 = stateVariables["/d6b"].stateValues.numericalfs[2]; + let d9_1 = stateVariables["/d9"].stateValues.numericalfs[0]; + let d9_2 = stateVariables["/d9"].stateValues.numericalfs[1]; + let d10_1 = stateVariables["/d10"].stateValues.numericalfs[0]; + let d10_2 = stateVariables["/d10"].stateValues.numericalfs[1]; + let d10_3 = stateVariables["/d10"].stateValues.numericalfs[2]; + let d11_1 = stateVariables["/d11"].stateValues.numericalfs[0]; + let d11_2 = stateVariables["/d11"].stateValues.numericalfs[1]; + let d11_3 = stateVariables["/d11"].stateValues.numericalfs[2]; + let d11_4 = stateVariables["/d11"].stateValues.numericalfs[3]; + let d12_1 = stateVariables["/d12"].stateValues.numericalfs[0]; + let d12_2 = stateVariables["/d12"].stateValues.numericalfs[1]; + let d12_3 = stateVariables["/d12"].stateValues.numericalfs[2]; + let d12_4 = stateVariables["/d12"].stateValues.numericalfs[3]; + + for (let i = 1; i <= 21; i++) { + let x = 0.2 * (i - 11); + expect(d1_1(x)).closeTo(2 * x, 1e-10); + expect(d1_2(x)).closeTo(3 * x ** 2, 1e-10); + expect(d2_1(x)).closeTo(2 * x, 1e-10); + expect(d2_2(x)).closeTo(3 * x ** 2, 1e-10); + expect(d2b_1(x)).closeTo(2 * x, 1e-10); + expect(d2b_2(x)).closeTo(3 * x ** 2, 1e-10); + expect(d2c_1(x)).closeTo(2 * x, 1e-10); + expect(d2c_2(x)).closeTo(3 * x ** 2, 1e-10); + expect(d5_1(x)).closeTo(Math.cos(x), 1e-10); + expect(d5_2(x)).closeTo(-Math.sin(x), 1e-10); + expect(d5b_1(x)).closeTo(Math.cos(x), 1e-10); + expect(d5b_2(x)).closeTo(-Math.sin(x), 1e-10); + expect(d6_1(x)).closeTo(2 * Math.exp(2 * x), 1e-10); + expect(d6_2(x)).closeTo(1, 1e-10); + if (x === 0) { + expect(d6_3(x)).eq(Infinity); + } else { + expect(d6_3(x)).closeTo(1 / x, 1e-10); + } + expect(d6b_1(x)).closeTo(2 * Math.exp(2 * x), 1e-10); + expect(d6b_2(x)).closeTo(1, 1e-10); + if (x === 0) { + expect(d6b_3(x)).eq(Infinity); + } else { + expect(d6b_3(x)).closeTo(1 / x, 1e-10); + } + expect(d9_1(x)).closeTo(0, 1e-10); + expect(d9_2(x)).closeTo(0, 1e-10); + expect(d10_1(x)).closeTo(0, 1e-10); + expect(d10_2(x)).closeTo(0, 1e-10); + expect(d10_3(x)).closeTo(0, 1e-10); + expect(d11_1(x)).closeTo(0, 1e-10); + expect(d11_2(x)).closeTo(0, 1e-10); + expect(d11_3(x)).closeTo(0, 1e-10); + expect(d11_4(x)).closeTo(0, 1e-10); + expect(d12_1(x)).closeTo(0, 1e-10); + expect(d12_2(x)).closeTo(0, 1e-10); + expect(d12_3(x)).closeTo(0, 1e-10); + expect(d12_4(x)).closeTo(0, 1e-10); + } + }); + + // check to make sure fixed bug where wasn't displaying inside + it("derivative displayed inside ", async () => { + let core = await createTestCore({ + doenetML: ` +

Let f(x) = sin(x).

+

Then f'(x) = $f.

+ `, + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq("Let f(x) = sin(x)."); + expect(stateVariables["/p2"].stateValues.text).eq( + "Then f'(x) = cos(x).", + ); + }); + + it("derivatives of interpolated function", async () => { + let core = await createTestCore({ + doenetML: ` + + + $f + $d1 + $d2 + $d3 + $d4 + $d5 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let f1 = stateVariables["/f"].stateValues.numericalfs[0]; + let d1 = stateVariables["/d1"].stateValues.numericalfs[0]; + let d2 = stateVariables["/d2"].stateValues.numericalfs[0]; + let d3 = stateVariables["/d3"].stateValues.numericalfs[0]; + let d4 = stateVariables["/d4"].stateValues.numericalfs[0]; + let d5 = stateVariables["/d5"].stateValues.numericalfs[0]; + let d6 = stateVariables["/d6"].stateValues.numericalfs[0]; + + for (let x = -10; x <= 10; x += 0.5) { + expect(f1(x)).eq((x - 3) ** 2 + 4); + expect(d1(x)).eq(2 * (x - 3)); + expect(d2(x)).eq(2); + expect(d3(x)).eq(0); + expect(d4(x)).eq(0); + expect(d5(x)).eq(0); + expect(d6(x)).eq(0); + } + }); + + it("derivatives of interpolated function 2", async () => { + let core = await createTestCore({ + doenetML: ` + + + $f + $d1 + $d2 + $d3 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let dx = 0.0001; + + let f = stateVariables["/f"].stateValues.numericalfs[0]; + let d1 = stateVariables["/d1"].stateValues.numericalfs[0]; + let d2 = stateVariables["/d2"].stateValues.numericalfs[0]; + let d3 = stateVariables["/d3"].stateValues.numericalfs[0]; + let d4 = stateVariables["/d4"].stateValues.numericalfs[0]; + + // make sure we don't get within dx of a grid point + for (let x = -10.02412412; x <= 10; x += 0.5) { + let f0 = f(x); + let f1 = f(x + dx); + let fp05 = d1(x + dx / 2); + expect(fp05).closeTo((f1 - f0) / dx, 1e-6); + + let fpn05 = d1(x - dx / 2); + let fpp0 = d2(x); + expect(fpp0).closeTo((fp05 - fpn05) / dx, 1e-6); + + let fpp1 = d2(x + dx); + let fppp05 = d3(x + dx / 2); + expect(fppp05).closeTo((fpp1 - fpp0) / dx, 1e-6); + + let fpppn05 = d3(x - dx / 2); + let fpppp0 = d4(x); + expect(fpppp0).closeTo((fppp05 - fpppn05) / dx, 1e-6); + } + }); + + it("derivatives of interpolated function that is not a function", async () => { + let core = await createTestCore({ + doenetML: ` + + + $f + + +

f(3) = $$f(3)

+

f'(3) = $$df(3)

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("f(3) = NaN"); + expect(stateVariables["/p2"].stateValues.text).eq("f'(3) = NaN"); + + let f = stateVariables["/f"].stateValues.numericalfs[0]; + let df = stateVariables["/df"].stateValues.numericalfs[0]; + expect(f(3)).eqls(NaN); + expect(df(3)).eqls(NaN); + }); + + it("derivatives of interpolated function specified with variables", async () => { + let core = await createTestCore({ + doenetML: ` + + + + $f + $g + + $f + $g + + $f + $g + + $f + $g + + $f + $g + + $f + $g + + $f + $g + + $f + $g + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let dx = 0.0001; + + let f = stateVariables["/f"].stateValues.numericalfs[0]; + let df1 = stateVariables["/df1"].stateValues.numericalfs[0]; + let df1b = stateVariables["/df1b"].stateValues.numericalfs[0]; + let df2 = stateVariables["/df2"].stateValues.numericalfs[0]; + let df3 = stateVariables["/df3"].stateValues.numericalfs[0]; + let df4 = stateVariables["/df4"].stateValues.numericalfs[0]; + let g = stateVariables["/g"].stateValues.numericalfs[0]; + let dg1 = stateVariables["/dg1"].stateValues.numericalfs[0]; + let dg1b = stateVariables["/dg1b"].stateValues.numericalfs[0]; + let dg2 = stateVariables["/dg2"].stateValues.numericalfs[0]; + let dg3 = stateVariables["/dg3"].stateValues.numericalfs[0]; + let dg4 = stateVariables["/dg4"].stateValues.numericalfs[0]; + let zero1 = stateVariables["/zero1"].stateValues.numericalfs[0]; + let zero2 = stateVariables["/zero2"].stateValues.numericalfs[0]; + let zero3 = stateVariables["/zero3"].stateValues.numericalfs[0]; + let zero4 = stateVariables["/zero4"].stateValues.numericalfs[0]; + let zero5 = stateVariables["/zero5"].stateValues.numericalfs[0]; + let zero6 = stateVariables["/zero6"].stateValues.numericalfs[0]; + + // make sure we don't get within dx of a grid point + for (let x = -10.02412412; x <= 10; x += 0.5) { + let f_0 = f(x); + let f_1 = f(x + dx); + let df1_05 = df1(x + dx / 2); + let df1b_05 = df1b(x + dx / 2); + expect(df1_05).closeTo((f_1 - f_0) / dx, 1e-6); + expect(df1b_05).eq(df1_05); + + let g_0 = g(x); + let g_1 = g(x + dx); + let dg1_05 = dg1(x + dx / 2); + let dg1b_05 = dg1b(x + dx / 2); + expect(dg1_05).closeTo((g_1 - g_0) / dx, 1e-6); + expect(dg1b_05).eq(dg1_05); + + let df1_n05 = df1(x - dx / 2); + let df2_0 = df2(x); + expect(df2_0).closeTo((df1b_05 - df1_n05) / dx, 1e-6); + + let dg1_n05 = dg1(x - dx / 2); + let dg2_0 = dg2(x); + expect(dg2_0).closeTo((dg1b_05 - dg1_n05) / dx, 1e-6); + + let df2_1 = df2(x + dx); + let df3_05 = df3(x + dx / 2); + expect(df3_05).closeTo((df2_1 - df2_0) / dx, 1e-6); + + let dg2_1 = dg2(x + dx); + let dg3_05 = dg3(x + dx / 2); + expect(dg3_05).closeTo((dg2_1 - dg2_0) / dx, 1e-6); + + let df3_n05 = df3(x - dx / 2); + let df4_0 = df4(x); + expect(df4_0).closeTo((df3_05 - df3_n05) / dx, 1e-6); + + let dg3_n05 = dg3(x - dx / 2); + let dg4_0 = dg4(x); + expect(dg4_0).closeTo((dg3_05 - dg3_n05) / dx, 1e-6); + + expect(zero1(x)).eq(0); + expect(zero2(x)).eq(0); + expect(zero3(x)).eq(0); + expect(zero4(x)).eq(0); + expect(zero5(x)).eq(0); + expect(zero6(x)).eq(0); + } + }); + + it("derivatives of interpolated function with changed variables", async () => { + let core = await createTestCore({ + doenetML: ` + + $f + $g + + $f + $g + $h + + $f + $g + $h + + $f + $g + $h + + $f + $g + $h + + $f + $g + $h + + $f + $g + $h + + $f + $g + $h + + $f + $g + $h + + $f + $g + $h + + $f + $g + $h + + 0.0001 + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let dx = 0.0001; + + let f = stateVariables["/f"].stateValues.numericalfs[0]; + let df1 = stateVariables["/df1"].stateValues.numericalfs[0]; + let df1b = stateVariables["/df1b"].stateValues.numericalfs[0]; + let df2 = stateVariables["/df2"].stateValues.numericalfs[0]; + let df2b = stateVariables["/df2b"].stateValues.numericalfs[0]; + let df3 = stateVariables["/df3"].stateValues.numericalfs[0]; + let df4 = stateVariables["/df4"].stateValues.numericalfs[0]; + let g = stateVariables["/g"].stateValues.numericalfs[0]; + let dg1 = stateVariables["/dg1"].stateValues.numericalfs[0]; + let dg1b = stateVariables["/dg1b"].stateValues.numericalfs[0]; + let dg2 = stateVariables["/dg2"].stateValues.numericalfs[0]; + let dg2b = stateVariables["/dg2b"].stateValues.numericalfs[0]; + let dg3 = stateVariables["/dg3"].stateValues.numericalfs[0]; + let dg4 = stateVariables["/dg4"].stateValues.numericalfs[0]; + let h = stateVariables["/h"].stateValues.numericalfs[0]; + let dh1 = stateVariables["/dh1"].stateValues.numericalfs[0]; + let dh1b = stateVariables["/dh1b"].stateValues.numericalfs[0]; + let dh2 = stateVariables["/dh2"].stateValues.numericalfs[0]; + let dh2b = stateVariables["/dh2b"].stateValues.numericalfs[0]; + let dh3 = stateVariables["/dh3"].stateValues.numericalfs[0]; + let dh4 = stateVariables["/dh4"].stateValues.numericalfs[0]; + let zero1 = stateVariables["/zero1"].stateValues.numericalfs[0]; + let zero2 = stateVariables["/zero2"].stateValues.numericalfs[0]; + let zero3 = stateVariables["/zero3"].stateValues.numericalfs[0]; + let zero4 = stateVariables["/zero4"].stateValues.numericalfs[0]; + let zero5 = stateVariables["/zero5"].stateValues.numericalfs[0]; + let zero6 = stateVariables["/zero6"].stateValues.numericalfs[0]; + let zero7 = stateVariables["/zero7"].stateValues.numericalfs[0]; + let zero8 = stateVariables["/zero8"].stateValues.numericalfs[0]; + let zero9 = stateVariables["/zero9"].stateValues.numericalfs[0]; + let zero10 = stateVariables["/zero10"].stateValues.numericalfs[0]; + let zero11 = stateVariables["/zero11"].stateValues.numericalfs[0]; + let zero12 = stateVariables["/zero12"].stateValues.numericalfs[0]; + + let i = 0; + + // make sure we don't get within dx of a grid point + for (let x = -10.02412412; x <= 10; x += 3.1) { + i++; + + let f_0 = f(x); + let f_1 = f(x + dx); + let df1_05 = df1(x + dx / 2); + let df1b_05 = df1b(x + dx / 2); + expect(df1_05).closeTo((f_1 - f_0) / dx, 1e-6); + expect(df1b_05).eq(df1_05); + + let f_0a = stateVariables[`/t${i}/f_0`].stateValues.value.tree; + expect(f_0a).closeTo(f_0, 1e-10); + let df1_05a = + stateVariables[`/t${i}/df1_05`].stateValues.value.tree; + expect(df1_05a).closeTo(df1_05, 1e-10); + let df1b_05a = + stateVariables[`/t${i}/df1b_05`].stateValues.value.tree; + expect(df1b_05a).closeTo(df1b_05, 1e-10); + + let g_0 = g(x); + let g_1 = g(x + dx); + expect(g_0).eq(f_0); + expect(g_1).eq(f_1); + let dg1_05 = dg1(x + dx / 2); + let dg1b_05 = dg1b(x + dx / 2); + expect(dg1_05).closeTo((g_1 - g_0) / dx, 1e-6); + expect(dg1b_05).eq(dg1_05); + + let g_0a = stateVariables[`/t${i}/g_0`].stateValues.value.tree; + expect(g_0a).closeTo(f_0, 1e-10); + let dg1_05a = + stateVariables[`/t${i}/dg1_05`].stateValues.value.tree; + expect(dg1_05a).closeTo(df1_05, 1e-10); + let dg1b_05a = + stateVariables[`/t${i}/dg1b_05`].stateValues.value.tree; + expect(dg1b_05a).closeTo(df1b_05, 1e-10); + + let h_0 = h(x); + let h_1 = h(x + dx); + expect(h_0).eq(f_0); + expect(h_1).eq(f_1); + let dh1_05 = dh1(x + dx / 2); + let dh1b_05 = dh1b(x + dx / 2); + expect(dh1_05).closeTo((h_1 - h_0) / dx, 1e-6); + expect(dh1b_05).eq(dh1_05); + + let h_0a = stateVariables[`/t${i}/h_0`].stateValues.value.tree; + expect(h_0a).closeTo(f_0, 1e-10); + let dh1_05a = + stateVariables[`/t${i}/dh1_05`].stateValues.value.tree; + expect(dh1_05a).closeTo(df1_05, 1e-10); + let dh1b_05a = + stateVariables[`/t${i}/dh1b_05`].stateValues.value.tree; + expect(dh1b_05a).closeTo(df1b_05, 1e-10); + + let df1_n05 = df1(x - dx / 2); + let df2_0 = df2(x); + expect(df2_0).closeTo((df1b_05 - df1_n05) / dx, 1e-6); + + let df2_0a = stateVariables[`/t${i}/df2_0`].stateValues.value.tree; + expect(df2_0a).closeTo(df2_0, 1e-10); + + let dg2_0 = dg2(x); + expect(dg2_0).eq(df2_0); + + let dg2_0a = stateVariables[`/t${i}/dg2_0`].stateValues.value.tree; + expect(dg2_0a).closeTo(df2_0, 1e-10); + + let dh2_0 = dh2(x); + expect(dh2_0).eq(df2_0); + + let dh2_0a = stateVariables[`/t${i}/dh2_0`].stateValues.value.tree; + expect(dh2_0a).closeTo(df2_0, 1e-10); + + let df2b_0 = df2b(x); + expect(df2b_0).eq(df2_0); + + let df2b_0a = + stateVariables[`/t${i}/df2b_0`].stateValues.value.tree; + expect(df2b_0a).closeTo(df2b_0, 1e-10); + + let dg2b_0 = dg2b(x); + expect(dg2b_0).eq(dg2_0); + + let dg2b_0a = + stateVariables[`/t${i}/dg2b_0`].stateValues.value.tree; + expect(dg2b_0a).closeTo(df2b_0, 1e-10); + + let dh2b_0 = dh2b(x); + expect(dh2b_0).eq(dh2_0); + + let dh2b_0a = + stateVariables[`/t${i}/dh2b_0`].stateValues.value.tree; + expect(dh2b_0a).closeTo(df2b_0, 1e-10); + + let df2_1 = df2(x + dx); + let df3_05 = df3(x + dx / 2); + expect(df3_05).closeTo((df2_1 - df2_0) / dx, 1e-6); + + let df3_05a = + stateVariables[`/t${i}/df3_05`].stateValues.value.tree; + expect(df3_05a).closeTo(df3_05, 1e-10); + + let dg3_05 = dg3(x + dx / 2); + expect(dg3_05).eq(df3_05); + + let dg3_05a = + stateVariables[`/t${i}/dg3_05`].stateValues.value.tree; + expect(dg3_05a).closeTo(df3_05, 1e-10); + + let dh3_05 = dh3(x + dx / 2); + expect(dh3_05).eq(df3_05); + + let dh3_05a = + stateVariables[`/t${i}/dh3_05`].stateValues.value.tree; + expect(dh3_05a).closeTo(df3_05, 1e-10); + + let df3_n05 = df3(x - dx / 2); + let df4_0 = df4(x); + expect(df4_0).closeTo((df3_05 - df3_n05) / dx, 1e-6); + + let df4_0a = stateVariables[`/t${i}/df4_0`].stateValues.value.tree; + expect(df4_0a).closeTo(df4_0, 1e-10); + + let dg4_0 = dg4(x); + expect(dg4_0).eq(df4_0); + + let dg4_0a = stateVariables[`/t${i}/dg4_0`].stateValues.value.tree; + expect(dg4_0a).closeTo(df4_0, 1e-10); + + let dh4_0 = dh4(x); + expect(dh4_0).eq(df4_0); + + let dh4_0a = stateVariables[`/t${i}/dh4_0`].stateValues.value.tree; + expect(dh4_0a).closeTo(df4_0, 1e-10); + + expect(zero1(x)).eq(0); + expect(zero2(x)).eq(0); + expect(zero3(x)).eq(0); + expect(zero4(x)).eq(0); + expect(zero5(x)).eq(0); + expect(zero6(x)).eq(0); + expect(zero7(x)).eq(0); + expect(zero8(x)).eq(0); + expect(zero9(x)).eq(0); + expect(zero10(x)).eq(0); + expect(zero11(x)).eq(0); + expect(zero12(x)).eq(0); + } + }); + + it("derivatives of interpolated function with changed variables, subscript", async () => { + let core = await createTestCore({ + doenetML: ` + + $f + + $f + $g + + $f + $g + + $f + $g + + $f + $g + + $f + $g + + $f + $g + + $f + $g + + $f + $g + + $f + $g + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let dx = 0.0001; + + let f = stateVariables["/f"].stateValues.numericalfs[0]; + let df1 = stateVariables["/df1"].stateValues.numericalfs[0]; + let df1b = stateVariables["/df1b"].stateValues.numericalfs[0]; + let df2 = stateVariables["/df2"].stateValues.numericalfs[0]; + let df2b = stateVariables["/df2b"].stateValues.numericalfs[0]; + let df3 = stateVariables["/df3"].stateValues.numericalfs[0]; + let df4 = stateVariables["/df4"].stateValues.numericalfs[0]; + let g = stateVariables["/g"].stateValues.numericalfs[0]; + let dg1 = stateVariables["/dg1"].stateValues.numericalfs[0]; + let dg1b = stateVariables["/dg1b"].stateValues.numericalfs[0]; + let dg2 = stateVariables["/dg2"].stateValues.numericalfs[0]; + let dg2b = stateVariables["/dg2b"].stateValues.numericalfs[0]; + let dg3 = stateVariables["/dg3"].stateValues.numericalfs[0]; + let dg4 = stateVariables["/dg4"].stateValues.numericalfs[0]; + let zero1 = stateVariables["/zero1"].stateValues.numericalfs[0]; + let zero2 = stateVariables["/zero2"].stateValues.numericalfs[0]; + let zero3 = stateVariables["/zero3"].stateValues.numericalfs[0]; + let zero4 = stateVariables["/zero4"].stateValues.numericalfs[0]; + let zero5 = stateVariables["/zero5"].stateValues.numericalfs[0]; + let zero6 = stateVariables["/zero6"].stateValues.numericalfs[0]; + + // make sure we don't get within dx of a grid point + for (let x = -10.02412412; x <= 10; x += 0.5) { + let f_0 = f(x); + let f_1 = f(x + dx); + let df1_05 = df1(x + dx / 2); + let df1b_05 = df1b(x + dx / 2); + expect(df1_05).closeTo((f_1 - f_0) / dx, 1e-6); + expect(df1b_05).eq(df1_05); + + let dg1_05 = dg1(x + dx / 2); + let dg1b_05 = dg1b(x + dx / 2); + expect(dg1_05).eq(dg1_05); + expect(dg1b_05).eq(dg1_05); + + let df1_n05 = df1(x - dx / 2); + let df2_0 = df2(x); + expect(df2_0).closeTo((df1b_05 - df1_n05) / dx, 1e-6); + + let dg2_0 = dg2(x); + expect(dg2_0).eq(df2_0); + + let df2b_0 = df2b(x); + expect(df2b_0).eq(df2_0); + + let dg2b_0 = dg2b(x); + expect(dg2b_0).eq(dg2_0); + + let df2_1 = df2(x + dx); + let df3_05 = df3(x + dx / 2); + expect(df3_05).closeTo((df2_1 - df2_0) / dx, 1e-6); + + let dg3_05 = dg3(x + dx / 2); + expect(dg3_05).eq(df3_05); + + let df3_n05 = df3(x - dx / 2); + let df4_0 = df4(x); + expect(df4_0).closeTo((df3_05 - df3_n05) / dx, 1e-6); + + let dg4_0 = dg4(x); + expect(dg4_0).eq(df4_0); + + expect(zero1(x)).eq(0); + expect(zero2(x)).eq(0); + expect(zero3(x)).eq(0); + expect(zero4(x)).eq(0); + expect(zero5(x)).eq(0); + expect(zero6(x)).eq(0); + } + }); + + it("extrema of derivative", async () => { + let core = await createTestCore({ + doenetML: ` +

c_1 =

+

c_2 =

+

c_3 =

+

c_4 =

+

c_5 =

+

c_6 =

+

x =

+ + + $c_1 $x^5/20 - $c_1($c_2+$c_3+$c_4) $x^4/12 + + $c_1($c_2*$c_3 + $c_2 $c_4 + $c_3$c_4)$x^3/6 + - $c_1$c_2$c_3$c_4$x^2/2 + $c_5$x + $c_6 + + +

f($x) = + $formula +

+ +

f'($x) = + $f +

+ +

again, f'($x) = $fp{name="fp2"} +

+ + +

Number of minima of f':

+

Minima of f': $fp.minima

+ +

Number of maxima of f':

+

Maxima of f': $fp.maxima

+ +

To repeat:

+

Number of minima of f':

+

Minima of f': $fp2.minima

+ +

Number of maxima of f':

+

Maxima of f': $fp2.maxima

+ + `, + }); + + function fp( + x: number, + c1: number, + c2: number, + c3: number, + c4: number, + c5: number, + ) { + return ( + (c1 * x ** 4) / 4 - + (c1 * (c2 + c3 + c4) * x ** 3) / 3 + + (c1 * (c2 * c3 + c2 * c4 + c3 * c4) * x ** 2) / 2 - + c1 * c2 * c3 * c4 * x + + c5 + ); + } + + function fpMinima( + c1: number, + c2: number, + c3: number, + c4: number, + c5: number, + ) { + let extrema = [c2, c3, c4].sort((a, b) => a - b); + let minima: number[][] = []; + if (c1 > 0) { + minima.push([extrema[0], fp(extrema[0], c1, c2, c3, c4, c5)]); + minima.push([extrema[2], fp(extrema[2], c1, c2, c3, c4, c5)]); + } else { + minima.push([extrema[1], fp(extrema[1], c1, c2, c3, c4, c5)]); + } + return minima; + } + + function fpMaxima( + c1: number, + c2: number, + c3: number, + c4: number, + c5: number, + ) { + let extrema = [c2, c3, c4].sort((a, b) => a - b); + let maxima: number[][] = []; + if (c1 > 0) { + maxima.push([extrema[1], fp(extrema[1], c1, c2, c3, c4, c5)]); + } else { + maxima.push([extrema[0], fp(extrema[0], c1, c2, c3, c4, c5)]); + maxima.push([extrema[2], fp(extrema[2], c1, c2, c3, c4, c5)]); + } + return maxima; + } + + async function verifyExtrema(c1, c2, c3, c4, c5) { + let minima = fpMinima(c1, c2, c3, c4, c5); + let nMinima = minima.length; + let maxima = fpMaxima(c1, c2, c3, c4, c5); + let nMaxima = maxima.length; + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/nMinima"].stateValues.value).eq(nMinima); + expect(stateVariables["/nMinima2"].stateValues.value).eq(nMinima); + + expect(stateVariables["/min1"].stateValues.text).eq( + `( ${minima[0][0]}, ${me.math.round(minima[0][1], 5)} )`, + ); + expect(stateVariables["/min12"].stateValues.text).eq( + `( ${minima[0][0]}, ${me.math.round(minima[0][1], 5)} )`, + ); + if (nMinima === 2) { + expect(stateVariables["/min2"].stateValues.text).eq( + `( ${minima[1][0]}, ${me.math.round(minima[1][1], 5)} )`, + ); + expect(stateVariables["/min22"].stateValues.text).eq( + `( ${minima[1][0]}, ${me.math.round(minima[1][1], 5)} )`, + ); + } else { + expect(stateVariables["/min2"]).eq(undefined); + expect(stateVariables["/min22"]).eq(undefined); + } + + expect(stateVariables["/nMaxima"].stateValues.value).eq(nMaxima); + expect(stateVariables["/nMaxima2"].stateValues.value).eq(nMaxima); + + expect(stateVariables["/max1"].stateValues.text).eq( + `( ${maxima[0][0]}, ${me.math.round(maxima[0][1], 5)} )`, + ); + expect(stateVariables["/max12"].stateValues.text).eq( + `( ${maxima[0][0]}, ${me.math.round(maxima[0][1], 5)} )`, + ); + if (nMaxima === 2) { + expect(stateVariables["/max2"].stateValues.text).eq( + `( ${maxima[1][0]}, ${me.math.round(maxima[1][1], 5)} )`, + ); + expect(stateVariables["/max22"].stateValues.text).eq( + `( ${maxima[1][0]}, ${me.math.round(maxima[1][1], 5)} )`, + ); + } else { + expect(stateVariables["/max2"]).eq(undefined); + expect(stateVariables["/max22"]).eq(undefined); + } + } + + let c1 = 1, + c2 = 1, + c3 = 3, + c4 = 4, + c5 = 5, + c6 = 1, + v = "x"; + + await verifyExtrema(c1, c2, c3, c4, c5); + + c1 = 3; + await updateMathInputValue({ + latex: c1.toString(), + componentName: "/c_1", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + c2 = -5; + await updateMathInputValue({ + latex: c2.toString(), + componentName: "/c_2", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + c3 = 1; + await updateMathInputValue({ + latex: c3.toString(), + componentName: "/c_3", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + c4 = -6; + await updateMathInputValue({ + latex: c4.toString(), + componentName: "/c_4", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + c5 = 3; + await updateMathInputValue({ + latex: c5.toString(), + componentName: "/c_5", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + c6 = 2; + await updateMathInputValue({ + latex: c6.toString(), + componentName: "/c_6", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + v = "y"; + await updateMathInputValue({ + latex: v, + componentName: "/x", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + c1 = 2; + await updateMathInputValue({ + latex: c1.toString(), + componentName: "/c_1", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + c2 = 4; + await updateMathInputValue({ + latex: c2.toString(), + componentName: "/c_2", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + c3 = -8; + await updateMathInputValue({ + latex: c3.toString(), + componentName: "/c_3", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + c4 = 9; + await updateMathInputValue({ + latex: c4.toString(), + componentName: "/c_4", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + c5 = -2; + await updateMathInputValue({ + latex: c5.toString(), + componentName: "/c_5", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + c6 = 6; + await updateMathInputValue({ + latex: c6.toString(), + componentName: "/c_6", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + + v = "q"; + await updateMathInputValue({ + latex: v, + componentName: "/x", + core, + }); + await verifyExtrema(c1, c2, c3, c4, c5); + }); + + it("extrema of derivative of interpolated function", async () => { + let core = await createTestCore({ + doenetML: ` + + + $f + + + $fp{name="fp2"} + +

Number of minima of f':

+

Minima of f': $fp.minima

+ +

Number of maxima of f':

+

Maxima of f': $fp.maxima

+ +

To repeat:

+

Number of minima of f':

+

Minima of f': $fp2.minima

+ +

Number of maxima of f':

+

Maxima of f': $fp2.maxima

+ + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + let fp = stateVariables["/fp"].stateValues.numericalfs[0]; + + expect(stateVariables["/nMinima"].stateValues.value).eq(1); + expect(stateVariables["/nMinima2"].stateValues.value).eq(1); + + expect(stateVariables["/nMaxima"].stateValues.value).eq(2); + expect(stateVariables["/nMaxima2"].stateValues.value).eq(2); + + let max1x = (-5 - 3) / 2; + expect(stateVariables["/max1"].stateValues.text).eq( + `( ${max1x}, ${me.math.round(fp(max1x), 5)} )`, + ); + expect(stateVariables["/max12"].stateValues.text).eq( + `( ${max1x}, ${me.math.round(fp(max1x), 5)} )`, + ); + + let min1x = (-3 + 0) / 2; + + expect(stateVariables["/min1"].stateValues.text).eq( + `( ${min1x}, ${me.math.round(fp(min1x), 5)} )`, + ); + expect(stateVariables["/min12"].stateValues.text).eq( + `( ${min1x}, ${me.math.round(fp(min1x), 5)} )`, + ); + + let max2x = (0 + 6) / 2; + expect(stateVariables["/max2"].stateValues.text).eq( + `( ${max2x}, ${me.math.round(fp(max2x), 5)} )`, + ); + expect(stateVariables["/max22"].stateValues.text).eq( + `( ${max2x}, ${me.math.round(fp(max2x), 5)} )`, + ); + }); + + it("handle no child", async () => { + let core = await createTestCore({ + doenetML: ` +

+

$nothing

+ +

$$d1(0)

+

$$d2(0)

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/p2"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/p3"].stateValues.text).eq("NaN"); + expect(stateVariables["/p4"].stateValues.text).eq("NaN"); + + let d1 = stateVariables["/d1"].stateValues.numericalfs[0]; + let d2 = stateVariables["/d2"].stateValues.numericalfs[0]; + + expect(d1(0)).eqls(NaN); + expect(d2(0)).eqls(NaN); + }); +}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/booleanoperators.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/booleanoperators.cy.js deleted file mode 100644 index 65ce43d18..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/booleanoperators.cy.js +++ /dev/null @@ -1,714 +0,0 @@ -import { cesc } from "@doenet/utils"; - -describe("Boolean Operator Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("not", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - $_booleaninput1.value{assignNames="bv"} - true - false - `, - }, - "*", - ); - }); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/_not1")).should("have.text", "true"); - cy.get(cesc("#\\/_not2")).should("have.text", "false"); - cy.get(cesc("#\\/_not3")).should("have.text", "true"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bv"].stateValues.value).eq(false); - expect(stateVariables["/_not1"].stateValues.value).eq(true); - expect(stateVariables["/_not2"].stateValues.value).eq(false); - expect(stateVariables["/_not3"].stateValues.value).eq(true); - }); - - cy.log("check the box"); - cy.get(cesc("#\\/_booleaninput1")).click(); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/_not1")).should("have.text", "false"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/bv"].stateValues.value).eq(true); - expect(stateVariables["/_not1"].stateValues.value).eq(false); - }); - }); - - it("not when", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - $_mathinput1.value{assignNames="mv"} > 1 - `, - }, - "*", - ); - }); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/_not1")).should("have.text", "true"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_mathinput1"].stateValues.value).eq( - "\uff3f", - ); - expect(stateVariables["/mv"].stateValues.value).eq("\uff3f"); - expect(stateVariables["/_not1"].stateValues.value).eq(true); - }); - - cy.log("enter 2"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type("2{enter}", { - force: true, - }); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/_not1")).should("have.text", "false"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_mathinput1"].stateValues.value).eq(2); - expect(stateVariables["/mv"].stateValues.value).eq(2); - expect(stateVariables["/_not1"].stateValues.value).eq(false); - }); - - cy.log("enter 1"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/_not1")).should("have.text", "true"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_mathinput1"].stateValues.value).eq(1); - expect(stateVariables["/mv"].stateValues.value).eq(1); - expect(stateVariables["/_not1"].stateValues.value).eq(true); - }); - }); - - it("and", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - $_booleaninput1.value - $_booleaninput2.value - $_booleaninput3.value - - - $_booleaninput1.value - $_booleaninput2.value - $_booleaninput3.value - true - - - $_booleaninput1.value - $_booleaninput2.value - $_booleaninput3.value - false - -

- $_booleaninput1.value{assignNames="bv1"} - $_booleaninput2.value{assignNames="bv2"} - $_booleaninput3.value{assignNames="bv3"} -

- `, - }, - "*", - ); - }); - - cy.log("Test initial values"); - cy.get(cesc("#\\/_and1")).should("have.text", "false"); - cy.get(cesc("#\\/_and2")).should("have.text", "false"); - cy.get(cesc("#\\/_and3")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(false); - expect(stateVariables["/bv2"].stateValues.value).eq(false); - expect(stateVariables["/bv3"].stateValues.value).eq(false); - expect(stateVariables["/_and1"].stateValues.value).eq(false); - expect(stateVariables["/_and2"].stateValues.value).eq(false); - expect(stateVariables["/_and3"].stateValues.value).eq(false); - }); - - cy.log("check box 1"); - cy.get(cesc("#\\/_booleaninput1")).click(); - cy.get(cesc("#\\/bv1")).should("have.text", "true"); - cy.get(cesc("#\\/_and1")).should("have.text", "false"); - cy.get(cesc("#\\/_and2")).should("have.text", "false"); - cy.get(cesc("#\\/_and3")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(true); - expect(stateVariables["/bv2"].stateValues.value).eq(false); - expect(stateVariables["/bv3"].stateValues.value).eq(false); - expect(stateVariables["/_and1"].stateValues.value).eq(false); - expect(stateVariables["/_and2"].stateValues.value).eq(false); - expect(stateVariables["/_and3"].stateValues.value).eq(false); - }); - - cy.log("check box 2"); - cy.get(cesc("#\\/_booleaninput2")).click(); - cy.get(cesc("#\\/bv2")).should("have.text", "true"); - cy.get(cesc("#\\/_and1")).should("have.text", "false"); - cy.get(cesc("#\\/_and2")).should("have.text", "false"); - cy.get(cesc("#\\/_and3")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(true); - expect(stateVariables["/bv2"].stateValues.value).eq(true); - expect(stateVariables["/bv3"].stateValues.value).eq(false); - expect(stateVariables["/_and1"].stateValues.value).eq(false); - expect(stateVariables["/_and2"].stateValues.value).eq(false); - expect(stateVariables["/_and3"].stateValues.value).eq(false); - }); - - cy.log("check box 3"); - cy.get(cesc("#\\/_booleaninput3")).click(); - cy.get(cesc("#\\/bv3")).should("have.text", "true"); - cy.get(cesc("#\\/_and1")).should("have.text", "true"); - cy.get(cesc("#\\/_and2")).should("have.text", "true"); - cy.get(cesc("#\\/_and3")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - true, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(true); - expect(stateVariables["/bv2"].stateValues.value).eq(true); - expect(stateVariables["/bv3"].stateValues.value).eq(true); - expect(stateVariables["/_and1"].stateValues.value).eq(true); - expect(stateVariables["/_and2"].stateValues.value).eq(true); - expect(stateVariables["/_and3"].stateValues.value).eq(false); - }); - }); - - it("or", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - $_booleaninput1.value - $_booleaninput2.value - $_booleaninput3.value - - - $_booleaninput1.value - $_booleaninput2.value - $_booleaninput3.value - true - - - $_booleaninput1.value - $_booleaninput2.value - $_booleaninput3.value - false - -

- $_booleaninput1.value{assignNames="bv1"} - $_booleaninput2.value{assignNames="bv2"} - $_booleaninput3.value{assignNames="bv3"} -

- `, - }, - "*", - ); - }); - - cy.log("Test initial values"); - cy.get(cesc("#\\/_or1")).should("have.text", "false"); - cy.get(cesc("#\\/_or2")).should("have.text", "true"); - cy.get(cesc("#\\/_or3")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(false); - expect(stateVariables["/bv2"].stateValues.value).eq(false); - expect(stateVariables["/bv3"].stateValues.value).eq(false); - expect(stateVariables["/_or1"].stateValues.value).eq(false); - expect(stateVariables["/_or2"].stateValues.value).eq(true); - expect(stateVariables["/_or3"].stateValues.value).eq(false); - }); - - cy.log("check box 1"); - cy.get(cesc("#\\/_booleaninput1")).click(); - cy.get(cesc("#\\/bv1")).should("have.text", "true"); - cy.get(cesc("#\\/_or1")).should("have.text", "true"); - cy.get(cesc("#\\/_or2")).should("have.text", "true"); - cy.get(cesc("#\\/_or3")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(true); - expect(stateVariables["/bv2"].stateValues.value).eq(false); - expect(stateVariables["/bv3"].stateValues.value).eq(false); - expect(stateVariables["/_or1"].stateValues.value).eq(true); - expect(stateVariables["/_or2"].stateValues.value).eq(true); - expect(stateVariables["/_or3"].stateValues.value).eq(true); - }); - - cy.log("check box 2"); - cy.get(cesc("#\\/_booleaninput2")).click(); - cy.get(cesc("#\\/bv2")).should("have.text", "true"); - cy.get(cesc("#\\/_or1")).should("have.text", "true"); - cy.get(cesc("#\\/_or2")).should("have.text", "true"); - cy.get(cesc("#\\/_or3")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(true); - expect(stateVariables["/bv2"].stateValues.value).eq(true); - expect(stateVariables["/bv3"].stateValues.value).eq(false); - expect(stateVariables["/_or1"].stateValues.value).eq(true); - expect(stateVariables["/_or2"].stateValues.value).eq(true); - expect(stateVariables["/_or3"].stateValues.value).eq(true); - }); - - cy.log("check box 3"); - cy.get(cesc("#\\/_booleaninput3")).click(); - cy.get(cesc("#\\/bv3")).should("have.text", "true"); - cy.get(cesc("#\\/_or1")).should("have.text", "true"); - cy.get(cesc("#\\/_or2")).should("have.text", "true"); - cy.get(cesc("#\\/_or3")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - true, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(true); - expect(stateVariables["/bv2"].stateValues.value).eq(true); - expect(stateVariables["/bv3"].stateValues.value).eq(true); - expect(stateVariables["/_or1"].stateValues.value).eq(true); - expect(stateVariables["/_or2"].stateValues.value).eq(true); - expect(stateVariables["/_or3"].stateValues.value).eq(true); - }); - - cy.log("uncheck box 1"); - cy.get(cesc("#\\/_booleaninput1")).click(); - cy.get(cesc("#\\/bv1")).should("have.text", "false"); - cy.get(cesc("#\\/_or1")).should("have.text", "true"); - cy.get(cesc("#\\/_or2")).should("have.text", "true"); - cy.get(cesc("#\\/_or3")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - true, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(false); - expect(stateVariables["/bv2"].stateValues.value).eq(true); - expect(stateVariables["/bv3"].stateValues.value).eq(true); - expect(stateVariables["/_or1"].stateValues.value).eq(true); - expect(stateVariables["/_or2"].stateValues.value).eq(true); - expect(stateVariables["/_or3"].stateValues.value).eq(true); - }); - - cy.log("uncheck box 2"); - cy.get(cesc("#\\/_booleaninput2")).click(); - cy.get(cesc("#\\/bv2")).should("have.text", "false"); - cy.get(cesc("#\\/_or1")).should("have.text", "true"); - cy.get(cesc("#\\/_or2")).should("have.text", "true"); - cy.get(cesc("#\\/_or3")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - true, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(false); - expect(stateVariables["/bv2"].stateValues.value).eq(false); - expect(stateVariables["/bv3"].stateValues.value).eq(true); - expect(stateVariables["/_or1"].stateValues.value).eq(true); - expect(stateVariables["/_or2"].stateValues.value).eq(true); - expect(stateVariables["/_or3"].stateValues.value).eq(true); - }); - - cy.log("uncheck box 3"); - cy.get(cesc("#\\/_booleaninput3")).click(); - cy.get(cesc("#\\/bv3")).should("have.text", "false"); - cy.get(cesc("#\\/_or1")).should("have.text", "false"); - cy.get(cesc("#\\/_or2")).should("have.text", "true"); - cy.get(cesc("#\\/_or3")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(false); - expect(stateVariables["/bv2"].stateValues.value).eq(false); - expect(stateVariables["/bv3"].stateValues.value).eq(false); - expect(stateVariables["/_or1"].stateValues.value).eq(false); - expect(stateVariables["/_or2"].stateValues.value).eq(true); - expect(stateVariables["/_or3"].stateValues.value).eq(false); - }); - }); - - it("xor", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - $_booleaninput1.value - $_booleaninput2.value - $_booleaninput3.value - - - $_booleaninput1.value - $_booleaninput2.value - $_booleaninput3.value - true - - - $_booleaninput1.value - $_booleaninput2.value - $_booleaninput3.value - false - -

- $_booleaninput1.value{assignNames="bv1"} - $_booleaninput2.value{assignNames="bv2"} - $_booleaninput3.value{assignNames="bv3"} -

- `, - }, - "*", - ); - }); - - cy.log("Test initial values"); - cy.get(cesc("#\\/_xor1")).should("have.text", "false"); - cy.get(cesc("#\\/_xor2")).should("have.text", "true"); - cy.get(cesc("#\\/_xor3")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(false); - expect(stateVariables["/bv2"].stateValues.value).eq(false); - expect(stateVariables["/bv3"].stateValues.value).eq(false); - expect(stateVariables["/_xor1"].stateValues.value).eq(false); - expect(stateVariables["/_xor2"].stateValues.value).eq(true); - expect(stateVariables["/_xor3"].stateValues.value).eq(false); - }); - - cy.log("check box 1"); - cy.get(cesc("#\\/_booleaninput1")).click(); - cy.get(cesc("#\\/bv1")).should("have.text", "true"); - cy.get(cesc("#\\/_xor1")).should("have.text", "true"); - cy.get(cesc("#\\/_xor2")).should("have.text", "false"); - cy.get(cesc("#\\/_xor3")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(true); - expect(stateVariables["/bv2"].stateValues.value).eq(false); - expect(stateVariables["/bv3"].stateValues.value).eq(false); - expect(stateVariables["/_xor1"].stateValues.value).eq(true); - expect(stateVariables["/_xor2"].stateValues.value).eq(false); - expect(stateVariables["/_xor3"].stateValues.value).eq(true); - }); - - cy.log("check box 2"); - cy.get(cesc("#\\/_booleaninput2")).click(); - cy.get(cesc("#\\/bv2")).should("have.text", "true"); - cy.get(cesc("#\\/_xor1")).should("have.text", "false"); - cy.get(cesc("#\\/_xor2")).should("have.text", "false"); - cy.get(cesc("#\\/_xor3")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(true); - expect(stateVariables["/bv2"].stateValues.value).eq(true); - expect(stateVariables["/bv3"].stateValues.value).eq(false); - expect(stateVariables["/_xor1"].stateValues.value).eq(false); - expect(stateVariables["/_xor2"].stateValues.value).eq(false); - expect(stateVariables["/_xor3"].stateValues.value).eq(false); - }); - - cy.log("check box 3"); - cy.get(cesc("#\\/_booleaninput3")).click(); - cy.get(cesc("#\\/bv3")).should("have.text", "true"); - cy.get(cesc("#\\/_xor1")).should("have.text", "false"); - cy.get(cesc("#\\/_xor2")).should("have.text", "false"); - cy.get(cesc("#\\/_xor3")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - true, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(true); - expect(stateVariables["/bv2"].stateValues.value).eq(true); - expect(stateVariables["/bv3"].stateValues.value).eq(true); - expect(stateVariables["/_xor1"].stateValues.value).eq(false); - expect(stateVariables["/_xor2"].stateValues.value).eq(false); - expect(stateVariables["/_xor3"].stateValues.value).eq(false); - }); - - cy.log("uncheck box 1"); - cy.get(cesc("#\\/_booleaninput1")).click(); - cy.get(cesc("#\\/bv1")).should("have.text", "false"); - cy.get(cesc("#\\/_xor1")).should("have.text", "false"); - cy.get(cesc("#\\/_xor2")).should("have.text", "false"); - cy.get(cesc("#\\/_xor3")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - true, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(false); - expect(stateVariables["/bv2"].stateValues.value).eq(true); - expect(stateVariables["/bv3"].stateValues.value).eq(true); - expect(stateVariables["/_xor1"].stateValues.value).eq(false); - expect(stateVariables["/_xor2"].stateValues.value).eq(false); - expect(stateVariables["/_xor3"].stateValues.value).eq(false); - }); - - cy.log("uncheck box 2"); - cy.get(cesc("#\\/_booleaninput2")).click(); - cy.get(cesc("#\\/bv2")).should("have.text", "false"); - cy.get(cesc("#\\/_xor1")).should("have.text", "true"); - cy.get(cesc("#\\/_xor2")).should("have.text", "false"); - cy.get(cesc("#\\/_xor3")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - true, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(false); - expect(stateVariables["/bv2"].stateValues.value).eq(false); - expect(stateVariables["/bv3"].stateValues.value).eq(true); - expect(stateVariables["/_xor1"].stateValues.value).eq(true); - expect(stateVariables["/_xor2"].stateValues.value).eq(false); - expect(stateVariables["/_xor3"].stateValues.value).eq(true); - }); - - cy.log("uncheck box 3"); - cy.get(cesc("#\\/_booleaninput3")).click(); - cy.get(cesc("#\\/bv3")).should("have.text", "false"); - cy.get(cesc("#\\/_xor1")).should("have.text", "false"); - cy.get(cesc("#\\/_xor2")).should("have.text", "true"); - cy.get(cesc("#\\/_xor3")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput2"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_booleaninput3"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bv1"].stateValues.value).eq(false); - expect(stateVariables["/bv2"].stateValues.value).eq(false); - expect(stateVariables["/bv3"].stateValues.value).eq(false); - expect(stateVariables["/_xor1"].stateValues.value).eq(false); - expect(stateVariables["/_xor2"].stateValues.value).eq(true); - expect(stateVariables["/_xor3"].stateValues.value).eq(false); - }); - }); - - it("show point based on logic", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - - (1,2) - - - $_booleaninput1.value{assignNames="bv1"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_booleaninput1_input")); //wait for page to load - cy.log("Test initial values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_point1"].stateValues.hide).eq(true); - }); - - cy.log("check box to show point"); - cy.get(cesc("#\\/_booleaninput1")).click(); - cy.get(cesc("#\\/bv1")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_point1"].stateValues.hide).eq(false); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/booleanoperatorsonmath.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/booleanoperatorsonmath.cy.js deleted file mode 100644 index 09a61ffc4..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/booleanoperatorsonmath.cy.js +++ /dev/null @@ -1,500 +0,0 @@ -import { cesc } from "@doenet/utils"; - -describe("Boolean Operator on Math Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("isinteger, is number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - $n -

- $n - $asNum - isinteger($n) - isinteger($asNum) - $n/2 - $asNum/2 - 5 - 5.3 - $n - $asNum - isnumber($n) - isnumber($asNum) - $n/2 - $asNum/2 - 5 - 5.3 -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/int1")).should("have.text", "false"); - cy.get(cesc("#\\/int2")).should("have.text", "false"); - cy.get(cesc("#\\/int3")).should("have.text", "false"); - cy.get(cesc("#\\/int4")).should("have.text", "false"); - cy.get(cesc("#\\/int5")).should("have.text", "false"); - cy.get(cesc("#\\/int6")).should("have.text", "false"); - cy.get(cesc("#\\/int7")).should("have.text", "true"); - cy.get(cesc("#\\/int8")).should("have.text", "false"); - cy.get(cesc("#\\/num1")).should("have.text", "false"); - cy.get(cesc("#\\/num2")).should("have.text", "false"); - cy.get(cesc("#\\/num3")).should("have.text", "false"); - cy.get(cesc("#\\/num4")).should("have.text", "false"); - cy.get(cesc("#\\/num5")).should("have.text", "false"); - cy.get(cesc("#\\/num6")).should("have.text", "false"); - cy.get(cesc("#\\/num7")).should("have.text", "true"); - cy.get(cesc("#\\/num8")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(false); - expect(stateVariables["/int2"].stateValues.value).eq(false); - expect(stateVariables["/int3"].stateValues.value).eq(false); - expect(stateVariables["/int4"].stateValues.value).eq(false); - expect(stateVariables["/int5"].stateValues.value).eq(false); - expect(stateVariables["/int6"].stateValues.value).eq(false); - expect(stateVariables["/int7"].stateValues.value).eq(true); - expect(stateVariables["/int8"].stateValues.value).eq(false); - expect(stateVariables["/num1"].stateValues.value).eq(false); - expect(stateVariables["/num2"].stateValues.value).eq(false); - expect(stateVariables["/num3"].stateValues.value).eq(false); - expect(stateVariables["/num4"].stateValues.value).eq(false); - expect(stateVariables["/num5"].stateValues.value).eq(false); - expect(stateVariables["/num6"].stateValues.value).eq(false); - expect(stateVariables["/num7"].stateValues.value).eq(true); - expect(stateVariables["/num8"].stateValues.value).eq(true); - }); - - cy.log("36"); - cy.get(cesc("#\\/n") + " textarea").type("36{enter}", { force: true }); - cy.get(cesc("#\\/int1")).should("have.text", "true"); - cy.get(cesc("#\\/int2")).should("have.text", "true"); - cy.get(cesc("#\\/int3")).should("have.text", "true"); - cy.get(cesc("#\\/int4")).should("have.text", "true"); - cy.get(cesc("#\\/int5")).should("have.text", "true"); - cy.get(cesc("#\\/int6")).should("have.text", "true"); - cy.get(cesc("#\\/num1")).should("have.text", "true"); - cy.get(cesc("#\\/num2")).should("have.text", "true"); - cy.get(cesc("#\\/num3")).should("have.text", "true"); - cy.get(cesc("#\\/num4")).should("have.text", "true"); - cy.get(cesc("#\\/num5")).should("have.text", "true"); - cy.get(cesc("#\\/num6")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(true); - expect(stateVariables["/int2"].stateValues.value).eq(true); - expect(stateVariables["/int3"].stateValues.value).eq(true); - expect(stateVariables["/int4"].stateValues.value).eq(true); - expect(stateVariables["/int5"].stateValues.value).eq(true); - expect(stateVariables["/int6"].stateValues.value).eq(true); - expect(stateVariables["/num1"].stateValues.value).eq(true); - expect(stateVariables["/num2"].stateValues.value).eq(true); - expect(stateVariables["/num3"].stateValues.value).eq(true); - expect(stateVariables["/num4"].stateValues.value).eq(true); - expect(stateVariables["/num5"].stateValues.value).eq(true); - expect(stateVariables["/num6"].stateValues.value).eq(true); - }); - - cy.log("37"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}7{enter}", { - force: true, - }); - cy.get(cesc("#\\/int1")).should("have.text", "true"); - cy.get(cesc("#\\/int2")).should("have.text", "true"); - cy.get(cesc("#\\/int3")).should("have.text", "true"); - cy.get(cesc("#\\/int4")).should("have.text", "true"); - cy.get(cesc("#\\/int5")).should("have.text", "false"); - cy.get(cesc("#\\/int6")).should("have.text", "false"); - cy.get(cesc("#\\/num1")).should("have.text", "true"); - cy.get(cesc("#\\/num2")).should("have.text", "true"); - cy.get(cesc("#\\/num3")).should("have.text", "true"); - cy.get(cesc("#\\/num4")).should("have.text", "true"); - cy.get(cesc("#\\/num5")).should("have.text", "true"); - cy.get(cesc("#\\/num6")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(true); - expect(stateVariables["/int2"].stateValues.value).eq(true); - expect(stateVariables["/int3"].stateValues.value).eq(true); - expect(stateVariables["/int4"].stateValues.value).eq(true); - expect(stateVariables["/int5"].stateValues.value).eq(false); - expect(stateVariables["/int6"].stateValues.value).eq(false); - expect(stateVariables["/num1"].stateValues.value).eq(true); - expect(stateVariables["/num2"].stateValues.value).eq(true); - expect(stateVariables["/num3"].stateValues.value).eq(true); - expect(stateVariables["/num4"].stateValues.value).eq(true); - expect(stateVariables["/num5"].stateValues.value).eq(true); - expect(stateVariables["/num6"].stateValues.value).eq(true); - }); - - cy.log("37.1"); - cy.get(cesc("#\\/n") + " textarea").type("{end}.1{enter}", { - force: true, - }); - cy.get(cesc("#\\/int1")).should("have.text", "false"); - cy.get(cesc("#\\/int2")).should("have.text", "false"); - cy.get(cesc("#\\/int3")).should("have.text", "false"); - cy.get(cesc("#\\/int4")).should("have.text", "false"); - cy.get(cesc("#\\/int5")).should("have.text", "false"); - cy.get(cesc("#\\/int6")).should("have.text", "false"); - cy.get(cesc("#\\/num1")).should("have.text", "true"); - cy.get(cesc("#\\/num2")).should("have.text", "true"); - cy.get(cesc("#\\/num3")).should("have.text", "true"); - cy.get(cesc("#\\/num4")).should("have.text", "true"); - cy.get(cesc("#\\/num5")).should("have.text", "true"); - cy.get(cesc("#\\/num6")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(false); - expect(stateVariables["/int2"].stateValues.value).eq(false); - expect(stateVariables["/int3"].stateValues.value).eq(false); - expect(stateVariables["/int4"].stateValues.value).eq(false); - expect(stateVariables["/int5"].stateValues.value).eq(false); - expect(stateVariables["/int6"].stateValues.value).eq(false); - expect(stateVariables["/num1"].stateValues.value).eq(true); - expect(stateVariables["/num2"].stateValues.value).eq(true); - expect(stateVariables["/num3"].stateValues.value).eq(true); - expect(stateVariables["/num4"].stateValues.value).eq(true); - expect(stateVariables["/num5"].stateValues.value).eq(true); - expect(stateVariables["/num6"].stateValues.value).eq(true); - }); - - cy.log("42/3"); - cy.get(cesc("#\\/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}42/3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/int1")).should("have.text", "true"); - cy.get(cesc("#\\/int2")).should("have.text", "true"); - cy.get(cesc("#\\/int3")).should("have.text", "true"); - cy.get(cesc("#\\/int4")).should("have.text", "true"); - cy.get(cesc("#\\/int5")).should("have.text", "true"); - cy.get(cesc("#\\/int6")).should("have.text", "true"); - cy.get(cesc("#\\/num1")).should("have.text", "true"); - cy.get(cesc("#\\/num2")).should("have.text", "true"); - cy.get(cesc("#\\/num3")).should("have.text", "true"); - cy.get(cesc("#\\/num4")).should("have.text", "true"); - cy.get(cesc("#\\/num5")).should("have.text", "true"); - cy.get(cesc("#\\/num6")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(true); - expect(stateVariables["/int2"].stateValues.value).eq(true); - expect(stateVariables["/int3"].stateValues.value).eq(true); - expect(stateVariables["/int4"].stateValues.value).eq(true); - expect(stateVariables["/int5"].stateValues.value).eq(true); - expect(stateVariables["/int6"].stateValues.value).eq(true); - expect(stateVariables["/num1"].stateValues.value).eq(true); - expect(stateVariables["/num2"].stateValues.value).eq(true); - expect(stateVariables["/num3"].stateValues.value).eq(true); - expect(stateVariables["/num4"].stateValues.value).eq(true); - expect(stateVariables["/num5"].stateValues.value).eq(true); - expect(stateVariables["/num6"].stateValues.value).eq(true); - }); - - cy.log("-39.6/3.3"); - cy.get(cesc("#\\/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}-39.6/3.3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/int1")).should("have.text", "true"); - cy.get(cesc("#\\/int2")).should("have.text", "true"); - cy.get(cesc("#\\/int3")).should("have.text", "true"); - cy.get(cesc("#\\/int4")).should("have.text", "true"); - cy.get(cesc("#\\/int5")).should("have.text", "true"); - cy.get(cesc("#\\/int6")).should("have.text", "true"); - cy.get(cesc("#\\/num1")).should("have.text", "true"); - cy.get(cesc("#\\/num2")).should("have.text", "true"); - cy.get(cesc("#\\/num3")).should("have.text", "true"); - cy.get(cesc("#\\/num4")).should("have.text", "true"); - cy.get(cesc("#\\/num5")).should("have.text", "true"); - cy.get(cesc("#\\/num6")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(true); - expect(stateVariables["/int2"].stateValues.value).eq(true); - expect(stateVariables["/int3"].stateValues.value).eq(true); - expect(stateVariables["/int4"].stateValues.value).eq(true); - expect(stateVariables["/int5"].stateValues.value).eq(true); - expect(stateVariables["/int6"].stateValues.value).eq(true); - expect(stateVariables["/num1"].stateValues.value).eq(true); - expect(stateVariables["/num2"].stateValues.value).eq(true); - expect(stateVariables["/num3"].stateValues.value).eq(true); - expect(stateVariables["/num4"].stateValues.value).eq(true); - expect(stateVariables["/num5"].stateValues.value).eq(true); - expect(stateVariables["/num6"].stateValues.value).eq(true); - }); - - cy.log("x"); - cy.get(cesc("#\\/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/int1")).should("have.text", "false"); - cy.get(cesc("#\\/int2")).should("have.text", "false"); - cy.get(cesc("#\\/int3")).should("have.text", "false"); - cy.get(cesc("#\\/int4")).should("have.text", "false"); - cy.get(cesc("#\\/int5")).should("have.text", "false"); - cy.get(cesc("#\\/int6")).should("have.text", "false"); - cy.get(cesc("#\\/num1")).should("have.text", "false"); - cy.get(cesc("#\\/num2")).should("have.text", "false"); - cy.get(cesc("#\\/num3")).should("have.text", "false"); - cy.get(cesc("#\\/num4")).should("have.text", "false"); - cy.get(cesc("#\\/num5")).should("have.text", "false"); - cy.get(cesc("#\\/num6")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(false); - expect(stateVariables["/int2"].stateValues.value).eq(false); - expect(stateVariables["/int3"].stateValues.value).eq(false); - expect(stateVariables["/int4"].stateValues.value).eq(false); - expect(stateVariables["/int5"].stateValues.value).eq(false); - expect(stateVariables["/int6"].stateValues.value).eq(false); - expect(stateVariables["/num1"].stateValues.value).eq(false); - expect(stateVariables["/num2"].stateValues.value).eq(false); - expect(stateVariables["/num3"].stateValues.value).eq(false); - expect(stateVariables["/num4"].stateValues.value).eq(false); - expect(stateVariables["/num5"].stateValues.value).eq(false); - expect(stateVariables["/num6"].stateValues.value).eq(false); - }); - - cy.log("sqrt(4)"); - cy.get(cesc("#\\/n") + " textarea").type( - "{end}{backspace}{backspace}sqrt4{enter}", - { force: true }, - ); - cy.get(cesc("#\\/int1")).should("have.text", "true"); - cy.get(cesc("#\\/int2")).should("have.text", "true"); - cy.get(cesc("#\\/int3")).should("have.text", "true"); - cy.get(cesc("#\\/int4")).should("have.text", "true"); - cy.get(cesc("#\\/int5")).should("have.text", "true"); - cy.get(cesc("#\\/int6")).should("have.text", "true"); - cy.get(cesc("#\\/num1")).should("have.text", "true"); - cy.get(cesc("#\\/num2")).should("have.text", "true"); - cy.get(cesc("#\\/num3")).should("have.text", "true"); - cy.get(cesc("#\\/num4")).should("have.text", "true"); - cy.get(cesc("#\\/num5")).should("have.text", "true"); - cy.get(cesc("#\\/num6")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(true); - expect(stateVariables["/int2"].stateValues.value).eq(true); - expect(stateVariables["/int3"].stateValues.value).eq(true); - expect(stateVariables["/int4"].stateValues.value).eq(true); - expect(stateVariables["/int5"].stateValues.value).eq(true); - expect(stateVariables["/int6"].stateValues.value).eq(true); - expect(stateVariables["/num1"].stateValues.value).eq(true); - expect(stateVariables["/num2"].stateValues.value).eq(true); - expect(stateVariables["/num3"].stateValues.value).eq(true); - expect(stateVariables["/num4"].stateValues.value).eq(true); - expect(stateVariables["/num5"].stateValues.value).eq(true); - expect(stateVariables["/num6"].stateValues.value).eq(true); - }); - - cy.log("2sin(pi/4)^2"); - cy.get(cesc("#\\/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}2sin(pi/4){rightarrow}{rightarrow}^2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/int1")).should("have.text", "true"); - cy.get(cesc("#\\/int2")).should("have.text", "true"); - cy.get(cesc("#\\/int3")).should("have.text", "true"); - cy.get(cesc("#\\/int4")).should("have.text", "true"); - cy.get(cesc("#\\/int5")).should("have.text", "false"); - cy.get(cesc("#\\/int6")).should("have.text", "false"); - cy.get(cesc("#\\/num1")).should("have.text", "true"); - cy.get(cesc("#\\/num2")).should("have.text", "true"); - cy.get(cesc("#\\/num3")).should("have.text", "true"); - cy.get(cesc("#\\/num4")).should("have.text", "true"); - cy.get(cesc("#\\/num5")).should("have.text", "true"); - cy.get(cesc("#\\/num6")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(true); - expect(stateVariables["/int2"].stateValues.value).eq(true); - expect(stateVariables["/int3"].stateValues.value).eq(true); - expect(stateVariables["/int4"].stateValues.value).eq(true); - expect(stateVariables["/int5"].stateValues.value).eq(false); - expect(stateVariables["/int6"].stateValues.value).eq(false); - expect(stateVariables["/num1"].stateValues.value).eq(true); - expect(stateVariables["/num2"].stateValues.value).eq(true); - expect(stateVariables["/num3"].stateValues.value).eq(true); - expect(stateVariables["/num4"].stateValues.value).eq(true); - expect(stateVariables["/num5"].stateValues.value).eq(true); - expect(stateVariables["/num6"].stateValues.value).eq(true); - }); - - cy.log("1E-300"); - cy.get(cesc("#\\/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}1E-300{enter}", - { force: true }, - ); - cy.get(cesc("#\\/int1")).should("have.text", "false"); - cy.get(cesc("#\\/int2")).should("have.text", "false"); - cy.get(cesc("#\\/int3")).should("have.text", "false"); - cy.get(cesc("#\\/int4")).should("have.text", "false"); - cy.get(cesc("#\\/int5")).should("have.text", "false"); - cy.get(cesc("#\\/int6")).should("have.text", "false"); - cy.get(cesc("#\\/num1")).should("have.text", "true"); - cy.get(cesc("#\\/num2")).should("have.text", "true"); - cy.get(cesc("#\\/num3")).should("have.text", "true"); - cy.get(cesc("#\\/num4")).should("have.text", "true"); - cy.get(cesc("#\\/num5")).should("have.text", "true"); - cy.get(cesc("#\\/num6")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(false); - expect(stateVariables["/int2"].stateValues.value).eq(false); - expect(stateVariables["/int3"].stateValues.value).eq(false); - expect(stateVariables["/int4"].stateValues.value).eq(false); - expect(stateVariables["/int5"].stateValues.value).eq(false); - expect(stateVariables["/int6"].stateValues.value).eq(false); - expect(stateVariables["/num1"].stateValues.value).eq(true); - expect(stateVariables["/num2"].stateValues.value).eq(true); - expect(stateVariables["/num3"].stateValues.value).eq(true); - expect(stateVariables["/num4"].stateValues.value).eq(true); - expect(stateVariables["/num5"].stateValues.value).eq(true); - expect(stateVariables["/num6"].stateValues.value).eq(true); - }); - - cy.log("-0"); - cy.get(cesc("#\\/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}-0{enter}", - { force: true }, - ); - cy.get(cesc("#\\/int1")).should("have.text", "true"); - cy.get(cesc("#\\/int2")).should("have.text", "true"); - cy.get(cesc("#\\/int3")).should("have.text", "true"); - cy.get(cesc("#\\/int4")).should("have.text", "true"); - cy.get(cesc("#\\/int5")).should("have.text", "true"); - cy.get(cesc("#\\/int6")).should("have.text", "true"); - cy.get(cesc("#\\/num1")).should("have.text", "true"); - cy.get(cesc("#\\/num2")).should("have.text", "true"); - cy.get(cesc("#\\/num3")).should("have.text", "true"); - cy.get(cesc("#\\/num4")).should("have.text", "true"); - cy.get(cesc("#\\/num5")).should("have.text", "true"); - cy.get(cesc("#\\/num6")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(true); - expect(stateVariables["/int2"].stateValues.value).eq(true); - expect(stateVariables["/int3"].stateValues.value).eq(true); - expect(stateVariables["/int4"].stateValues.value).eq(true); - expect(stateVariables["/int5"].stateValues.value).eq(true); - expect(stateVariables["/int6"].stateValues.value).eq(true); - expect(stateVariables["/num1"].stateValues.value).eq(true); - expect(stateVariables["/num2"].stateValues.value).eq(true); - expect(stateVariables["/num3"].stateValues.value).eq(true); - expect(stateVariables["/num4"].stateValues.value).eq(true); - expect(stateVariables["/num5"].stateValues.value).eq(true); - expect(stateVariables["/num6"].stateValues.value).eq(true); - }); - - cy.log("0/0"); - cy.get(cesc("#\\/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}0/0{enter}", - { force: true }, - ); - cy.get(cesc("#\\/int1")).should("have.text", "false"); - cy.get(cesc("#\\/int2")).should("have.text", "false"); - cy.get(cesc("#\\/int3")).should("have.text", "false"); - cy.get(cesc("#\\/int4")).should("have.text", "false"); - cy.get(cesc("#\\/int5")).should("have.text", "false"); - cy.get(cesc("#\\/int6")).should("have.text", "false"); - cy.get(cesc("#\\/num1")).should("have.text", "false"); - cy.get(cesc("#\\/num2")).should("have.text", "false"); - cy.get(cesc("#\\/num3")).should("have.text", "false"); - cy.get(cesc("#\\/num4")).should("have.text", "false"); - cy.get(cesc("#\\/num5")).should("have.text", "false"); - cy.get(cesc("#\\/num6")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(false); - expect(stateVariables["/int2"].stateValues.value).eq(false); - expect(stateVariables["/int3"].stateValues.value).eq(false); - expect(stateVariables["/int4"].stateValues.value).eq(false); - expect(stateVariables["/int5"].stateValues.value).eq(false); - expect(stateVariables["/int6"].stateValues.value).eq(false); - expect(stateVariables["/num1"].stateValues.value).eq(false); - expect(stateVariables["/num2"].stateValues.value).eq(false); - expect(stateVariables["/num3"].stateValues.value).eq(false); - expect(stateVariables["/num4"].stateValues.value).eq(false); - expect(stateVariables["/num5"].stateValues.value).eq(false); - expect(stateVariables["/num6"].stateValues.value).eq(false); - }); - - cy.log("10/0"); - cy.get(cesc("#\\/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}10/0{enter}", - { force: true }, - ); - cy.get(cesc("#\\/int1")).should("have.text", "false"); - cy.get(cesc("#\\/int2")).should("have.text", "false"); - cy.get(cesc("#\\/int3")).should("have.text", "false"); - cy.get(cesc("#\\/int4")).should("have.text", "false"); - cy.get(cesc("#\\/int5")).should("have.text", "false"); - cy.get(cesc("#\\/int6")).should("have.text", "false"); - cy.get(cesc("#\\/num1")).should("have.text", "false"); - cy.get(cesc("#\\/num2")).should("have.text", "false"); - cy.get(cesc("#\\/num3")).should("have.text", "false"); - cy.get(cesc("#\\/num4")).should("have.text", "false"); - cy.get(cesc("#\\/num5")).should("have.text", "false"); - cy.get(cesc("#\\/num6")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(false); - expect(stateVariables["/int2"].stateValues.value).eq(false); - expect(stateVariables["/int3"].stateValues.value).eq(false); - expect(stateVariables["/int4"].stateValues.value).eq(false); - expect(stateVariables["/int5"].stateValues.value).eq(false); - expect(stateVariables["/int6"].stateValues.value).eq(false); - expect(stateVariables["/num1"].stateValues.value).eq(false); - expect(stateVariables["/num2"].stateValues.value).eq(false); - expect(stateVariables["/num3"].stateValues.value).eq(false); - expect(stateVariables["/num4"].stateValues.value).eq(false); - expect(stateVariables["/num5"].stateValues.value).eq(false); - expect(stateVariables["/num6"].stateValues.value).eq(false); - }); - - cy.log("10/-0"); - cy.get(cesc("#\\/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}10/-0{enter}", - { force: true }, - ); - cy.get(cesc("#\\/int1")).should("have.text", "false"); - cy.get(cesc("#\\/int2")).should("have.text", "false"); - cy.get(cesc("#\\/int3")).should("have.text", "false"); - cy.get(cesc("#\\/int4")).should("have.text", "false"); - cy.get(cesc("#\\/int5")).should("have.text", "false"); - cy.get(cesc("#\\/int6")).should("have.text", "false"); - cy.get(cesc("#\\/num1")).should("have.text", "false"); - cy.get(cesc("#\\/num2")).should("have.text", "false"); - cy.get(cesc("#\\/num3")).should("have.text", "false"); - cy.get(cesc("#\\/num4")).should("have.text", "false"); - cy.get(cesc("#\\/num5")).should("have.text", "false"); - cy.get(cesc("#\\/num6")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int1"].stateValues.value).eq(false); - expect(stateVariables["/int2"].stateValues.value).eq(false); - expect(stateVariables["/int3"].stateValues.value).eq(false); - expect(stateVariables["/int4"].stateValues.value).eq(false); - expect(stateVariables["/int5"].stateValues.value).eq(false); - expect(stateVariables["/int6"].stateValues.value).eq(false); - expect(stateVariables["/num1"].stateValues.value).eq(false); - expect(stateVariables["/num2"].stateValues.value).eq(false); - expect(stateVariables["/num3"].stateValues.value).eq(false); - expect(stateVariables["/num4"].stateValues.value).eq(false); - expect(stateVariables["/num5"].stateValues.value).eq(false); - expect(stateVariables["/num6"].stateValues.value).eq(false); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/functionoperators.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/functionoperators.cy.js deleted file mode 100644 index 21b06c817..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/functionoperators.cy.js +++ /dev/null @@ -1,4693 +0,0 @@ -import me from "math-expressions"; -import { cesc, cesc2, createFunctionFromDefinition } from "@doenet/utils"; - -function nInDOM(n) { - if (n < 0) { - return `−${Math.abs(n)}`; - } else { - return String(n); - } -} - -describe("Function Operator Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("clamp function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x^3 - $original - $original - -

- - - - -

-

- - - - -

-

- - - - -

-

- $_map2{name="m4"} -

-

- $_map3{name="m5"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let map1Replacements = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map1ReplacementAnchors = map1Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map2Replacements = stateVariables["/_map2"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map2ReplacementAnchors = map2Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map3Replacements = stateVariables["/_map3"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map3ReplacementAnchors = map3Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map4Replacements = stateVariables["/m4"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map4ReplacementAnchors = map4Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map5Replacements = stateVariables["/m5"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map5ReplacementAnchors = map5Replacements.map((x) => - cesc2("#" + x.componentName), - ); - - let clamp01 = (x) => Math.min(1, Math.max(0, x)); - let clampn35 = (x) => Math.min(5, Math.max(-3, x)); - let indToVal = (ind) => me.math.round((0.2 * (ind - 11)) ** 3, 3); - - cy.log("Check values in DOM"); - for (let i = 1; i <= 21; i++) { - cy.get(map1ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - indToVal(i).toString(), - ); - }); - - cy.get(map2ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - clamp01(indToVal(i)).toString(), - ); - }); - - cy.get(map3ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - clampn35(indToVal(i)).toString(), - ); - }); - - cy.get(map4ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - clamp01(indToVal(i)).toString(), - ); - }); - - cy.get(map5ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - clampn35(indToVal(i)).toString(), - ); - }); - } - - cy.log("check mapped state values"); - cy.window().then(async (win) => { - for (let i = 1; i <= 21; i++) { - expect( - stateVariables[map1Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(indToVal(i), 1e-10); - expect( - stateVariables[map2Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(clamp01(indToVal(i)), 1e-10); - expect( - stateVariables[map3Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(clampn35(indToVal(i)), 1e-10); - expect( - stateVariables[map4Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(clamp01(indToVal(i)), 1e-10); - expect( - stateVariables[map5Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(clampn35(indToVal(i)), 1e-10); - } - }); - - cy.log("check functions created from fDefinition"); - cy.window().then(async (win) => { - let f01 = createFunctionFromDefinition( - stateVariables["/clamp01"].stateValues.fDefinitions[0], - ); - let fn35 = createFunctionFromDefinition( - stateVariables["/clampn35"].stateValues.fDefinitions[0], - ); - - for (let i = 1; i <= 21; i++) { - let x = 0.2 * (i - 11); - expect(f01(x)).closeTo(clamp01(indToVal(i)), 1e-10); - expect(fn35(x)).closeTo(clampn35(indToVal(i)), 1e-10); - } - }); - }); - }); - - it("clamp function, numeric", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x^3 - $original - $original - -

- - - - -

-

- - - - -

-

- - - - -

-

- $_map2{name="m4"} -

-

- $_map3{name="m5"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let map1Replacements = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map1ReplacementAnchors = map1Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map2Replacements = stateVariables["/_map2"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map2ReplacementAnchors = map2Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map3Replacements = stateVariables["/_map3"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map3ReplacementAnchors = map3Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map4Replacements = stateVariables["/m4"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map4ReplacementAnchors = map4Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map5Replacements = stateVariables["/m5"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map5ReplacementAnchors = map5Replacements.map((x) => - cesc2("#" + x.componentName), - ); - - let clamp01 = (x) => Math.min(1, Math.max(0, x)); - let clampn35 = (x) => Math.min(5, Math.max(-3, x)); - let indToVal = (ind) => me.math.round((0.2 * (ind - 11)) ** 3, 3); - - cy.log("Check values in DOM"); - for (let i = 1; i <= 21; i++) { - cy.get(map1ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - indToVal(i).toString(), - ); - }); - - cy.get(map2ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - clamp01(indToVal(i)).toString(), - ); - }); - - cy.get(map3ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - clampn35(indToVal(i)).toString(), - ); - }); - - cy.get(map4ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - clamp01(indToVal(i)).toString(), - ); - }); - - cy.get(map5ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - clampn35(indToVal(i)).toString(), - ); - }); - } - - cy.log("check mapped state values"); - cy.window().then(async (win) => { - for (let i = 1; i <= 21; i++) { - expect( - stateVariables[map1Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(indToVal(i), 1e-10); - expect( - stateVariables[map2Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(clamp01(indToVal(i)), 1e-10); - expect( - stateVariables[map3Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(clampn35(indToVal(i)), 1e-10); - expect( - stateVariables[map4Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(clamp01(indToVal(i)), 1e-10); - expect( - stateVariables[map5Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(clampn35(indToVal(i)), 1e-10); - } - }); - - cy.log("check functions created from fDefinition"); - cy.window().then(async (win) => { - let f01 = createFunctionFromDefinition( - stateVariables["/clamp01"].stateValues.fDefinitions[0], - ); - let fn35 = createFunctionFromDefinition( - stateVariables["/clampn35"].stateValues.fDefinitions[0], - ); - - for (let i = 1; i <= 21; i++) { - let x = 0.2 * (i - 11); - expect(f01(x)).closeTo(clamp01(indToVal(i)), 1e-10); - expect(fn35(x)).closeTo(clampn35(indToVal(i)), 1e-10); - } - }); - }); - }); - - it("clamp function, labeled", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x^3 - $original - $original - -

- - - - -

-

- - - - -

-

- - - - -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/original"].stateValues.label).eq("orig"); - expect(stateVariables["/clamp01"].stateValues.label).eq("clamp 1"); - expect(stateVariables["/clampn35"].stateValues.label).eq("clamp 2"); - - let map1Replacements = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map1ReplacementAnchors = map1Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map2Replacements = stateVariables["/_map2"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map2ReplacementAnchors = map2Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map3Replacements = stateVariables["/_map3"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map3ReplacementAnchors = map3Replacements.map((x) => - cesc2("#" + x.componentName), - ); - - let clamp01 = (x) => Math.min(1, Math.max(0, x)); - let clampn35 = (x) => Math.min(5, Math.max(-3, x)); - let indToVal = (ind) => me.math.round((ind - 3) ** 3, 3); - - cy.log("Check values in DOM"); - for (let i = 1; i <= 5; i++) { - cy.get(map1ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - indToVal(i).toString(), - ); - }); - - cy.get(map2ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - clamp01(indToVal(i)).toString(), - ); - }); - - cy.get(map3ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - clampn35(indToVal(i)).toString(), - ); - }); - } - - cy.log("check mapped state values"); - cy.window().then(async (win) => { - for (let i = 1; i <= 5; i++) { - expect( - stateVariables[map1Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(indToVal(i), 1e-10); - expect( - stateVariables[map2Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(clamp01(indToVal(i)), 1e-10); - expect( - stateVariables[map3Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(clampn35(indToVal(i)), 1e-10); - } - }); - - cy.log("check functions created from fDefinition"); - cy.window().then(async (win) => { - let f01 = createFunctionFromDefinition( - stateVariables["/clamp01"].stateValues.fDefinitions[0], - ); - let fn35 = createFunctionFromDefinition( - stateVariables["/clampn35"].stateValues.fDefinitions[0], - ); - - for (let i = 1; i <= 5; i++) { - let x = i - 3; - expect(f01(x)).closeTo(clamp01(indToVal(i)), 1e-10); - expect(fn35(x)).closeTo(clampn35(indToVal(i)), 1e-10); - } - }); - }); - }); - - it("wrap function", () => { - // Note: added domain [-2,2] to reduce time spent calculating all the extrema - // when calling returnAllStateVariables1() - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x^3 - $original - $original - -

- - - - -

-

- - - - -

-

- - - - -

-

- $_map2{name="m4"} -

-

- $_map3{name="m5"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let map1Replacements = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map1ReplacementAnchors = map1Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map2Replacements = stateVariables["/_map2"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map2ReplacementAnchors = map2Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map3Replacements = stateVariables["/_map3"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map3ReplacementAnchors = map3Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map4Replacements = stateVariables["/m4"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map4ReplacementAnchors = map4Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map5Replacements = stateVariables["/m5"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map5ReplacementAnchors = map5Replacements.map((x) => - cesc2("#" + x.componentName), - ); - - let wrap01 = (x) => me.math.round(me.math.mod(x, 1), 3); - let wrapn23 = (x) => me.math.round(-2 + me.math.mod(x + 2, 5), 3); - let indToVal = (ind) => me.math.round((0.2 * (ind - 11)) ** 3, 3); - - cy.log("Check values in DOM"); - - for (let i = 1; i <= 21; i++) { - cy.get(map1ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - indToVal(i).toString(), - ); - }); - - cy.get(map2ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - wrap01(indToVal(i)).toString(), - ); - }); - - cy.get(map3ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - wrapn23(indToVal(i)).toString(), - ); - }); - - cy.get(map4ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - wrap01(indToVal(i)).toString(), - ); - }); - - cy.get(map5ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - wrapn23(indToVal(i)).toString(), - ); - }); - } - - cy.log("check mapped state values"); - cy.window().then(async (win) => { - for (let i = 1; i <= 21; i++) { - expect( - stateVariables[map1Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(indToVal(i), 1e-10); - expect( - stateVariables[map2Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(wrap01(indToVal(i)), 1e-10); - expect( - stateVariables[map3Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(wrapn23(indToVal(i)), 1e-10); - expect( - stateVariables[map4Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(wrap01(indToVal(i)), 1e-10); - expect( - stateVariables[map5Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(wrapn23(indToVal(i)), 1e-10); - } - }); - - cy.log("check functions created from fDefinition"); - cy.window().then(async (win) => { - let f01 = createFunctionFromDefinition( - stateVariables["/wrap01"].stateValues.fDefinitions[0], - ); - let fn23 = createFunctionFromDefinition( - stateVariables["/wrapn23"].stateValues.fDefinitions[0], - ); - - for (let i = 1; i <= 21; i++) { - let x = 0.2 * (i - 11); - expect(f01(x)).closeTo(wrap01(indToVal(i)), 1e-10); - expect(fn23(x)).closeTo(wrapn23(indToVal(i)), 1e-10); - } - }); - }); - }); - - it("wrap function, numeric", () => { - // Note: added domain [-2,2] to reduce time spent calculating all the extrema - // when calling returnAllStateVariables1() - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x^3 - $original - $original - -

- - - - -

-

- - - - -

-

- - - - -

-

- $_map2{name="m4"} -

-

- $_map3{name="m5"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let map1Replacements = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map1ReplacementAnchors = map1Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map2Replacements = stateVariables["/_map2"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map2ReplacementAnchors = map2Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map3Replacements = stateVariables["/_map3"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map3ReplacementAnchors = map3Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map4Replacements = stateVariables["/m4"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map4ReplacementAnchors = map4Replacements.map((x) => - cesc2("#" + x.componentName), - ); - let map5Replacements = stateVariables["/m5"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements, - ], - [], - ); - let map5ReplacementAnchors = map5Replacements.map((x) => - cesc2("#" + x.componentName), - ); - - let wrap01 = (x) => me.math.round(me.math.mod(x, 1), 3); - let wrapn23 = (x) => me.math.round(-2 + me.math.mod(x + 2, 5), 3); - let indToVal = (ind) => me.math.round((0.2 * (ind - 11)) ** 3, 3); - - cy.log("Check values in DOM"); - - for (let i = 1; i <= 21; i++) { - cy.get(map1ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - indToVal(i).toString(), - ); - }); - - cy.get(map2ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - wrap01(indToVal(i)).toString(), - ); - }); - - cy.get(map3ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - wrapn23(indToVal(i)).toString(), - ); - }); - - cy.get(map4ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - wrap01(indToVal(i)).toString(), - ); - }); - - cy.get(map5ReplacementAnchors[i - 1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - wrapn23(indToVal(i)).toString(), - ); - }); - } - - cy.log("check mapped state values"); - cy.window().then(async (win) => { - for (let i = 1; i <= 21; i++) { - expect( - stateVariables[map1Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(indToVal(i), 1e-10); - expect( - stateVariables[map2Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(wrap01(indToVal(i)), 1e-10); - expect( - stateVariables[map3Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(wrapn23(indToVal(i)), 1e-10); - expect( - stateVariables[map4Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(wrap01(indToVal(i)), 1e-10); - expect( - stateVariables[map5Replacements[i - 1].componentName] - .stateValues.value, - ).closeTo(wrapn23(indToVal(i)), 1e-10); - } - }); - - cy.log("check functions created from fDefinition"); - cy.window().then(async (win) => { - let f01 = createFunctionFromDefinition( - stateVariables["/wrap01"].stateValues.fDefinitions[0], - ); - let fn23 = createFunctionFromDefinition( - stateVariables["/wrapn23"].stateValues.fDefinitions[0], - ); - - for (let i = 1; i <= 21; i++) { - let x = 0.2 * (i - 11); - expect(f01(x)).closeTo(wrap01(indToVal(i)), 1e-10); - expect(fn23(x)).closeTo(wrapn23(indToVal(i)), 1e-10); - } - }); - }); - }); - - it("derivative", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a =

-

b =

-

c =

-

x =

- - - $a sin($b$x + $c) - - -

f($x) = - $formula -

- -

f'($x) = - $f -

- - - $f - $g - - - $f - - - - - $g - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2("#/_m5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(x)=sin(x+1)"); - }); - cy.get(cesc2("#/_m6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f′(x)=cos(x+1)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let x1 = 3, - y1 = Math.sin(4); - let x2 = 3, - y2 = Math.cos(4); - - expect( - me.fromAst(stateVariables["/f"].stateValues.formula).toString(), - ).eq("sin(x + 1)"); - expect( - me.fromAst(stateVariables["/g"].stateValues.formula).toString(), - ).eq("cos(x + 1)"); - expect(stateVariables["/_point1"].stateValues.xs[0]).closeTo( - x1, - 1e-12, - ); - expect(stateVariables["/_point1"].stateValues.xs[1]).closeTo( - y1, - 1e-12, - ); - expect(stateVariables["/_point2"].stateValues.xs[0]).closeTo( - x2, - 1e-12, - ); - expect(stateVariables["/_point2"].stateValues.xs[1]).closeTo( - y2, - 1e-12, - ); - - let f = createFunctionFromDefinition( - stateVariables["/f"].stateValues.fDefinitions[0], - ); - let g = createFunctionFromDefinition( - stateVariables["/g"].stateValues.fDefinitions[0], - ); - - for (let i = 1; i <= 21; i++) { - let x = 0.2 * (i - 11); - expect(f(x)).closeTo(Math.sin(x + 1), 1e-10); - expect(g(x)).closeTo(Math.cos(x + 1), 1e-10); - } - }); - - cy.window().then(async (win) => { - let x1 = -3, - y1 = Math.sin(-2); - let x2 = 5, - y2 = Math.cos(6); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: x1, y: y1 }, - }); - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point2", - args: { x: x2, y: y2 }, - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect( - me.fromAst(stateVariables["/f"].stateValues.formula).toString(), - ).eq("sin(x + 1)"); - expect( - me.fromAst(stateVariables["/g"].stateValues.formula).toString(), - ).eq("cos(x + 1)"); - expect(stateVariables["/_point1"].stateValues.xs[0]).closeTo( - x1, - 1e-12, - ); - expect(stateVariables["/_point1"].stateValues.xs[1]).closeTo( - y1, - 1e-12, - ); - expect(stateVariables["/_point2"].stateValues.xs[0]).closeTo( - x2, - 1e-12, - ); - expect(stateVariables["/_point2"].stateValues.xs[1]).closeTo( - y2, - 1e-12, - ); - }); - - cy.get(cesc2("#/a") + " textarea").type(`{end}{backspace}2`, { - force: true, - }); - cy.get(cesc2("#/b") + " textarea").type(`{end}{backspace}pi`, { - force: true, - }); - cy.get(cesc2("#/c") + " textarea").type(`{end}{backspace}e`, { - force: true, - }); - cy.get(cesc2("#/x") + " textarea") - .type(`{end}{backspace}q`, { force: true }) - .blur(); - - cy.get(cesc2("#/_m5") + " .mjx-mrow").should( - "contain.text", - "f(q)=2sin(e+πq)", - ); - cy.get(cesc2("#/_m5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(q)=2sin(e+πq)"); - }); - cy.get(cesc2("#/_m6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f′(q)=2πcos(e+πq)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let x1 = -3, - y1 = 2 * Math.sin(Math.PI * -3 + Math.E); - let x2 = 5, - y2 = 2 * Math.PI * Math.cos(Math.PI * 5 + Math.E); - - expect( - me.fromAst(stateVariables["/f"].stateValues.formula).toString(), - ).eq("2 sin(e + π q)"); - expect( - me.fromAst(stateVariables["/g"].stateValues.formula).toString(), - ).eq("2 π cos(e + π q)"); - expect(stateVariables["/_point1"].stateValues.xs[0]).closeTo( - x1, - 1e-12, - ); - expect(stateVariables["/_point1"].stateValues.xs[1]).closeTo( - y1, - 1e-12, - ); - expect(stateVariables["/_point2"].stateValues.xs[0]).closeTo( - x2, - 1e-12, - ); - expect(stateVariables["/_point2"].stateValues.xs[1]).closeTo( - y2, - 1e-12, - ); - - let f = createFunctionFromDefinition( - stateVariables["/f"].stateValues.fDefinitions[0], - ); - let g = createFunctionFromDefinition( - stateVariables["/g"].stateValues.fDefinitions[0], - ); - - for (let i = 1; i <= 21; i++) { - let x = 0.2 * (i - 11); - expect(f(x)).closeTo(2 * Math.sin(Math.PI * x + Math.E), 1e-10); - expect(g(x)).closeTo( - 2 * Math.PI * Math.cos(Math.PI * x + Math.E), - 1e-10, - ); - } - }); - - cy.window().then(async (win) => { - let x1 = 9, - y1 = 2 * Math.sin(Math.PI * 9 + Math.E); - let x2 = -7, - y2 = 2 * Math.PI * Math.cos(Math.PI * -7 + Math.E); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: x1, y: y1 }, - }); - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point2", - args: { x: x2, y: y2 }, - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect( - me.fromAst(stateVariables["/f"].stateValues.formula).toString(), - ).eq("2 sin(e + π q)"); - expect( - me.fromAst(stateVariables["/g"].stateValues.formula).toString(), - ).eq("2 π cos(e + π q)"); - expect(stateVariables["/_point1"].stateValues.xs[0]).closeTo( - x1, - 1e-12, - ); - expect(stateVariables["/_point1"].stateValues.xs[1]).closeTo( - y1, - 1e-12, - ); - expect(stateVariables["/_point2"].stateValues.xs[0]).closeTo( - x2, - 1e-12, - ); - expect(stateVariables["/_point2"].stateValues.xs[1]).closeTo( - y2, - 1e-12, - ); - }); - }); - - it("derivative 2", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - sin(x) - e^(2y) - xyz - xyz - x^2 - x^2 - $x2 - $x2 - x^2sin(z) - x^2sin(z) - z2 - x^$a sin($var) - $f1 - $f1 - $f2 - $f2 - $f3 - $f3 - $f4 - $f4 - $f1 - $f2 - $f3 - $f4 - $f3 - $f4 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/d1"].stateValues.formula) - .equals(me.fromText("2x")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d2"].stateValues.formula) - .equals(me.fromText("2x")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d2b"].stateValues.formula) - .equals(me.fromText("2x")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d2c"].stateValues.formula) - .equals(me.fromText("2x")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d3"].stateValues.formula) - .equals(me.fromText("2x sin(z)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d4"].stateValues.formula) - .equals(me.fromText("x^2cos(z)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d4b"].stateValues.formula) - .equals(me.fromText("x^2cos(z)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d5"].stateValues.formula) - .equals(me.fromText("cos(x)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d5b"].stateValues.formula) - .equals(me.fromText("cos(x)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d6"].stateValues.formula) - .equals(me.fromText("2e^(2y)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d6b"].stateValues.formula) - .equals(me.fromText("2e^(2y)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d7"].stateValues.formula) - .equals(me.fromText("yz")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d7b"].stateValues.formula) - .equals(me.fromText("yz")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d8"].stateValues.formula) - .equals(me.fromText("xy")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d8b"].stateValues.formula) - .equals(me.fromText("xy")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d9"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d10"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d11"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d12"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d13"].stateValues.formula) - .equals(me.fromText("xz")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d14"].stateValues.formula) - .equals(me.fromText("xz")), - ).eq(true); - - let d1 = createFunctionFromDefinition( - stateVariables["/d1"].stateValues.fDefinitions[0], - ); - let d2 = createFunctionFromDefinition( - stateVariables["/d2"].stateValues.fDefinitions[0], - ); - let d2b = createFunctionFromDefinition( - stateVariables["/d2b"].stateValues.fDefinitions[0], - ); - let d2c = createFunctionFromDefinition( - stateVariables["/d2c"].stateValues.fDefinitions[0], - ); - let d5 = createFunctionFromDefinition( - stateVariables["/d5"].stateValues.fDefinitions[0], - ); - let d5b = createFunctionFromDefinition( - stateVariables["/d5b"].stateValues.fDefinitions[0], - ); - let d6 = createFunctionFromDefinition( - stateVariables["/d6"].stateValues.fDefinitions[0], - ); - let d6b = createFunctionFromDefinition( - stateVariables["/d6b"].stateValues.fDefinitions[0], - ); - let d9 = createFunctionFromDefinition( - stateVariables["/d9"].stateValues.fDefinitions[0], - ); - let d10 = createFunctionFromDefinition( - stateVariables["/d10"].stateValues.fDefinitions[0], - ); - let d11 = createFunctionFromDefinition( - stateVariables["/d11"].stateValues.fDefinitions[0], - ); - let d12 = createFunctionFromDefinition( - stateVariables["/d12"].stateValues.fDefinitions[0], - ); - - for (let i = 1; i <= 21; i++) { - let x = 0.2 * (i - 11); - expect(d1(x)).closeTo(2 * x, 1e-10); - expect(d2(x)).closeTo(2 * x, 1e-10); - expect(d2b(x)).closeTo(2 * x, 1e-10); - expect(d2c(x)).closeTo(2 * x, 1e-10); - expect(d5(x)).closeTo(Math.cos(x), 1e-10); - expect(d5b(x)).closeTo(Math.cos(x), 1e-10); - expect(d6(x)).closeTo(2 * Math.exp(2 * x), 1e-10); - expect(d6b(x)).closeTo(2 * Math.exp(2 * x), 1e-10); - expect(d9(x)).closeTo(0, 1e-10); - expect(d10(x)).closeTo(0, 1e-10); - expect(d11(x)).closeTo(0, 1e-10); - expect(d12(x)).closeTo(0, 1e-10); - } - }); - }); - - it("derivative 2, labeled", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - sin(x) - e^(2y) - xyz - xyz - x^2 - x^2 - $x2 - $x2 - x^2sin(z) - x^2sin(z) - z2 - x^$a sin($var) - $f1 - $f1 - $f2 - $f2 - $f3 - $f3 - $f4 - $f4 - $f1 - $f2 - $f3 - $f4 - $f3 - $f4 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/d1"].stateValues.label).eq("d1"); - expect(stateVariables["/d2"].stateValues.label).eq("d2"); - expect(stateVariables["/d2b"].stateValues.label).eq("d2b"); - expect(stateVariables["/d2c"].stateValues.label).eq("d2c"); - expect(stateVariables["/d3"].stateValues.label).eq("d3"); - expect(stateVariables["/d4"].stateValues.label).eq("d4"); - expect(stateVariables["/d4b"].stateValues.label).eq("d4b"); - expect(stateVariables["/d5"].stateValues.label).eq("d5"); - expect(stateVariables["/d5b"].stateValues.label).eq("d5b"); - expect(stateVariables["/d6"].stateValues.label).eq("d6"); - expect(stateVariables["/d6b"].stateValues.label).eq("d6b"); - expect(stateVariables["/d7"].stateValues.label).eq("d7"); - expect(stateVariables["/d7b"].stateValues.label).eq("d7b"); - expect(stateVariables["/d8"].stateValues.label).eq("d8"); - expect(stateVariables["/d8b"].stateValues.label).eq("d8b"); - expect(stateVariables["/d9"].stateValues.label).eq("d9"); - expect(stateVariables["/d10"].stateValues.label).eq("d10"); - expect(stateVariables["/d11"].stateValues.label).eq("d11"); - expect(stateVariables["/d12"].stateValues.label).eq("d12"); - expect(stateVariables["/d13"].stateValues.label).eq("d13"); - expect(stateVariables["/d14"].stateValues.label).eq("d14"); - - expect( - me - .fromAst(stateVariables["/d1"].stateValues.formula) - .equals(me.fromText("2x")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d2"].stateValues.formula) - .equals(me.fromText("2x")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d2b"].stateValues.formula) - .equals(me.fromText("2x")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d2c"].stateValues.formula) - .equals(me.fromText("2x")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d3"].stateValues.formula) - .equals(me.fromText("2x sin(z)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d4"].stateValues.formula) - .equals(me.fromText("x^2cos(z)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d4b"].stateValues.formula) - .equals(me.fromText("x^2cos(z)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d5"].stateValues.formula) - .equals(me.fromText("cos(x)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d5b"].stateValues.formula) - .equals(me.fromText("cos(x)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d6"].stateValues.formula) - .equals(me.fromText("2e^(2y)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d6b"].stateValues.formula) - .equals(me.fromText("2e^(2y)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d7"].stateValues.formula) - .equals(me.fromText("yz")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d7b"].stateValues.formula) - .equals(me.fromText("yz")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d8"].stateValues.formula) - .equals(me.fromText("xy")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d8b"].stateValues.formula) - .equals(me.fromText("xy")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d9"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d10"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d11"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d12"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d13"].stateValues.formula) - .equals(me.fromText("xz")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d14"].stateValues.formula) - .equals(me.fromText("xz")), - ).eq(true); - - let d1 = createFunctionFromDefinition( - stateVariables["/d1"].stateValues.fDefinitions[0], - ); - let d2 = createFunctionFromDefinition( - stateVariables["/d2"].stateValues.fDefinitions[0], - ); - let d2b = createFunctionFromDefinition( - stateVariables["/d2b"].stateValues.fDefinitions[0], - ); - let d2c = createFunctionFromDefinition( - stateVariables["/d2c"].stateValues.fDefinitions[0], - ); - let d5 = createFunctionFromDefinition( - stateVariables["/d5"].stateValues.fDefinitions[0], - ); - let d5b = createFunctionFromDefinition( - stateVariables["/d5b"].stateValues.fDefinitions[0], - ); - let d6 = createFunctionFromDefinition( - stateVariables["/d6"].stateValues.fDefinitions[0], - ); - let d6b = createFunctionFromDefinition( - stateVariables["/d6b"].stateValues.fDefinitions[0], - ); - let d9 = createFunctionFromDefinition( - stateVariables["/d9"].stateValues.fDefinitions[0], - ); - let d10 = createFunctionFromDefinition( - stateVariables["/d10"].stateValues.fDefinitions[0], - ); - let d11 = createFunctionFromDefinition( - stateVariables["/d11"].stateValues.fDefinitions[0], - ); - let d12 = createFunctionFromDefinition( - stateVariables["/d12"].stateValues.fDefinitions[0], - ); - - for (let i = 1; i <= 5; i++) { - let x = i - 3; - expect(d1(x)).closeTo(2 * x, 1e-10); - expect(d2(x)).closeTo(2 * x, 1e-10); - expect(d2b(x)).closeTo(2 * x, 1e-10); - expect(d2c(x)).closeTo(2 * x, 1e-10); - expect(d5(x)).closeTo(Math.cos(x), 1e-10); - expect(d5b(x)).closeTo(Math.cos(x), 1e-10); - expect(d6(x)).closeTo(2 * Math.exp(2 * x), 1e-10); - expect(d6b(x)).closeTo(2 * Math.exp(2 * x), 1e-10); - expect(d9(x)).closeTo(0, 1e-10); - expect(d10(x)).closeTo(0, 1e-10); - expect(d11(x)).closeTo(0, 1e-10); - expect(d12(x)).closeTo(0, 1e-10); - } - }); - }); - - it("specifying derivative variables of a function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- sin(x+y^2)z - sin(x+y^2)z - sin(x+y^2)z - sin(x_1+x_2^2)x_3 -

- -

- $f1 - $f1 - $f1 - $f1 - $f1 - $f1 - $f1 - $f1 -

- -

- $f2 - $f2 - $f2 - $f2 - $f2 - $f2 - $f2 - $f2 -

- -

- $f3 - $f3 - $f3 - $f3 - $f3 - $f3 - $f3 - $f3 -

- -

- $f4 - $f4 - $f4 - $f4 -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect( - me - .fromAst(stateVariables["/d11"].stateValues.formula) - .equals(me.fromText("cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d11"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d11"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d12"].stateValues.formula) - .equals(me.fromText("sin(x+y^2)")), - ).eq(true); - expect(stateVariables["/d12"].stateValues.variables).eqls(["z"]); - expect(stateVariables["/d12"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d13"].stateValues.formula) - .equals(me.fromText("cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d13"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d13"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d14"].stateValues.formula) - .equals(me.fromText("sin(x+y^2)")), - ).eq(true); - expect(stateVariables["/d14"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d14"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d15"].stateValues.formula) - .equals(me.fromText("2 y cos(x+y^2)")), - ).eq(true); - expect(stateVariables["/d15"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d15"].stateValues.derivVariables).eqls([ - "y", - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d16"].stateValues.formula) - .equals(me.fromText("-2 y cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d16"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d16"].stateValues.derivVariables).eqls([ - "x", - "x", - "y", - ]); - - expect( - me - .fromAst(stateVariables["/d17"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect(stateVariables["/d17"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d17"].stateValues.derivVariables).eqls([ - "u", - ]); - - expect( - me - .fromAst(stateVariables["/d18"].stateValues.formula) - .equals(me.fromText("-2 y cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d18"].stateValues.variables).eqls(["z"]); - expect(stateVariables["/d18"].stateValues.derivVariables).eqls([ - "x", - "x", - "y", - ]); - - expect( - me - .fromAst(stateVariables["/d21"].stateValues.formula) - .equals(me.fromText("sin(x+y^2)")), - ).eq(true); - expect(stateVariables["/d21"].stateValues.variables).eqls([ - "z", - "y", - "x", - ]); - expect(stateVariables["/d21"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d22"].stateValues.formula) - .equals(me.fromText("cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d22"].stateValues.variables).eqls(["x"]); - expect(stateVariables["/d22"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d23"].stateValues.formula) - .equals(me.fromText("cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d23"].stateValues.variables).eqls([ - "z", - "y", - "x", - ]); - expect(stateVariables["/d23"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d24"].stateValues.formula) - .equals(me.fromText("sin(x+y^2)")), - ).eq(true); - expect(stateVariables["/d24"].stateValues.variables).eqls([ - "z", - "y", - "x", - ]); - expect(stateVariables["/d24"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d25"].stateValues.formula) - .equals(me.fromText("2 y cos(x+y^2)")), - ).eq(true); - expect(stateVariables["/d25"].stateValues.variables).eqls([ - "z", - "y", - "x", - ]); - expect(stateVariables["/d25"].stateValues.derivVariables).eqls([ - "y", - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d26"].stateValues.formula) - .equals(me.fromText("-2 y cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d26"].stateValues.variables).eqls([ - "z", - "y", - "x", - ]); - expect(stateVariables["/d26"].stateValues.derivVariables).eqls([ - "x", - "x", - "y", - ]); - - expect( - me - .fromAst(stateVariables["/d27"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect(stateVariables["/d27"].stateValues.variables).eqls([ - "z", - "y", - "x", - ]); - expect(stateVariables["/d27"].stateValues.derivVariables).eqls([ - "u", - ]); - - expect( - me - .fromAst(stateVariables["/d28"].stateValues.formula) - .equals(me.fromText("-2 y cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d28"].stateValues.variables).eqls(["z"]); - expect(stateVariables["/d28"].stateValues.derivVariables).eqls([ - "x", - "x", - "y", - ]); - - expect( - me - .fromAst(stateVariables["/d31"].stateValues.formula) - .equals(me.fromText("cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d31"].stateValues.variables).eqls([ - "x", - "y", - ]); - expect(stateVariables["/d31"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d32"].stateValues.formula) - .equals(me.fromText("sin(x+y^2)")), - ).eq(true); - expect(stateVariables["/d32"].stateValues.variables).eqls(["z"]); - expect(stateVariables["/d32"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d33"].stateValues.formula) - .equals(me.fromText("cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d33"].stateValues.variables).eqls([ - "x", - "y", - ]); - expect(stateVariables["/d33"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d34"].stateValues.formula) - .equals(me.fromText("sin(x+y^2)")), - ).eq(true); - expect(stateVariables["/d34"].stateValues.variables).eqls([ - "x", - "y", - ]); - expect(stateVariables["/d34"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d35"].stateValues.formula) - .equals(me.fromText("2 y cos(x+y^2)")), - ).eq(true); - expect(stateVariables["/d35"].stateValues.variables).eqls([ - "x", - "y", - ]); - expect(stateVariables["/d35"].stateValues.derivVariables).eqls([ - "y", - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d36"].stateValues.formula) - .equals(me.fromText("-2 y cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d36"].stateValues.variables).eqls([ - "x", - "y", - ]); - expect(stateVariables["/d36"].stateValues.derivVariables).eqls([ - "x", - "x", - "y", - ]); - - expect( - me - .fromAst(stateVariables["/d37"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect(stateVariables["/d37"].stateValues.variables).eqls([ - "x", - "y", - ]); - expect(stateVariables["/d37"].stateValues.derivVariables).eqls([ - "u", - ]); - - expect( - me - .fromAst(stateVariables["/d38"].stateValues.formula) - .equals(me.fromText("-2 y cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d38"].stateValues.variables).eqls(["z"]); - expect(stateVariables["/d38"].stateValues.derivVariables).eqls([ - "x", - "x", - "y", - ]); - - expect( - me - .fromAst(stateVariables["/d41"].stateValues.formula) - .equals(me.fromText("cos(x_1+x_2^2)x_3")), - ).eq(true); - expect(stateVariables["/d41"].stateValues.variables).eqls([ - ["_", "x", 1], - ["_", "x", 2], - ["_", "x", 3], - ]); - expect(stateVariables["/d41"].stateValues.derivVariables).eqls([ - ["_", "x", 1], - ]); - - expect( - me - .fromAst(stateVariables["/d42"].stateValues.formula) - .equals(me.fromText("-2 x_2 sin(x_1+x_2^2)")), - ).eq(true); - expect(stateVariables["/d42"].stateValues.variables).eqls([ - ["_", "x", 1], - ["_", "x", 2], - ["_", "x", 3], - ]); - expect(stateVariables["/d42"].stateValues.derivVariables).eqls([ - ["_", "x", 1], - ["_", "x", 2], - ["_", "x", 3], - ]); - - expect( - me - .fromAst(stateVariables["/d43"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect(stateVariables["/d43"].stateValues.variables).eqls([ - ["_", "x", 1], - ["_", "x", 2], - ["_", "x", 3], - ]); - expect(stateVariables["/d43"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d44"].stateValues.formula) - .equals(me.fromText("-2 x_2 sin(x_1+x_2^2)")), - ).eq(true); - expect(stateVariables["/d44"].stateValues.variables).eqls([ - ["_", "x", 3], - ["_", "x", 2], - ["_", "x", 1], - ]); - expect(stateVariables["/d44"].stateValues.derivVariables).eqls([ - ["_", "x", 1], - ["_", "x", 2], - ["_", "x", 3], - ]); - }); - }); - - it("specifying derivative variables of an expression", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - sin(x+y^2)z - sin(x_1+x_2^2)x_3 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - $m1 - - - $m2 - $m2 - $m2 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect( - me - .fromAst(stateVariables["/d1"].stateValues.formula) - .equals(me.fromText("cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d1"].stateValues.variables).eqls(["x"]); - expect(stateVariables["/d1"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d2"].stateValues.formula) - .equals(me.fromText("cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d2"].stateValues.variables).eqls(["x"]); - expect(stateVariables["/d2"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d3"].stateValues.formula) - .equals(me.fromText("cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d3"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d3"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d4"].stateValues.formula) - .equals(me.fromText("sin(x+y^2)")), - ).eq(true); - expect(stateVariables["/d4"].stateValues.variables).eqls([ - "z", - "y", - "x", - ]); - expect(stateVariables["/d4"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d5"].stateValues.formula) - .equals(me.fromText("cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d5"].stateValues.variables).eqls(["x"]); - expect(stateVariables["/d5"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d5a"].stateValues.formula) - .equals(me.fromText("cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d5a"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d5a"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d6"].stateValues.formula) - .equals(me.fromText("-sin(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d6"].stateValues.variables).eqls(["x"]); - expect(stateVariables["/d6"].stateValues.derivVariables).eqls([ - "x", - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d6a"].stateValues.formula) - .equals(me.fromText("-sin(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d6a"].stateValues.variables).eqls(["x"]); - expect(stateVariables["/d6a"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d6b"].stateValues.formula) - .equals(me.fromText("-sin(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d6b"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d6b"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d6c"].stateValues.formula) - .equals(me.fromText("-sin(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d6c"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d6c"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d6d"].stateValues.formula) - .equals(me.fromText("-sin(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d6d"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d6d"].stateValues.derivVariables).eqls([ - "x", - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d7"].stateValues.formula) - .equals(me.fromText("-2 y sin(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d7"].stateValues.variables).eqls([ - "x", - "y", - ]); - expect(stateVariables["/d7"].stateValues.derivVariables).eqls([ - "x", - "y", - ]); - - expect( - me - .fromAst(stateVariables["/d7a"].stateValues.formula) - .equals(me.fromText("-2 y sin(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d7a"].stateValues.variables).eqls(["x"]); - expect(stateVariables["/d7a"].stateValues.derivVariables).eqls([ - "y", - ]); - - expect( - me - .fromAst(stateVariables["/d7b"].stateValues.formula) - .equals(me.fromText("-2 y sin(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d7b"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d7b"].stateValues.derivVariables).eqls([ - "y", - ]); - - expect( - me - .fromAst(stateVariables["/d7c"].stateValues.formula) - .equals(me.fromText("-2 y sin(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d7c"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d7c"].stateValues.derivVariables).eqls([ - "y", - ]); - - expect( - me - .fromAst(stateVariables["/d8"].stateValues.formula) - .equals(me.fromText("-2 y sin(x+y^2)")), - ).eq(true); - expect(stateVariables["/d8"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d8"].stateValues.derivVariables).eqls([ - "x", - "y", - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d8a"].stateValues.formula) - .equals(me.fromText("-2 y sin(x+y^2)")), - ).eq(true); - expect(stateVariables["/d8a"].stateValues.variables).eqls(["x"]); - expect(stateVariables["/d8a"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d8b"].stateValues.formula) - .equals(me.fromText("-2 y sin(x+y^2)")), - ).eq(true); - expect(stateVariables["/d8b"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d8b"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d8c"].stateValues.formula) - .equals(me.fromText("-2 y sin(x+y^2)")), - ).eq(true); - expect(stateVariables["/d8c"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d8c"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/d9"].stateValues.formula) - .equals(me.fromText("-2 y cos(x+y^2)")), - ).eq(true); - expect(stateVariables["/d9"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d9"].stateValues.derivVariables).eqls([ - "x", - "y", - "z", - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d9a"].stateValues.formula) - .equals(me.fromText("-2 y cos(x+y^2)")), - ).eq(true); - expect(stateVariables["/d9a"].stateValues.variables).eqls(["x"]); - expect(stateVariables["/d9a"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d9b"].stateValues.formula) - .equals(me.fromText("-2 y cos(x+y^2)")), - ).eq(true); - expect(stateVariables["/d9b"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d9b"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d9c"].stateValues.formula) - .equals(me.fromText("-2 y cos(x+y^2)")), - ).eq(true); - expect(stateVariables["/d9c"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d9c"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/d10"].stateValues.formula) - .equals(me.fromText("0")), - ).eq(true); - expect(stateVariables["/d10"].stateValues.variables).eqls(["q"]); - expect(stateVariables["/d10"].stateValues.derivVariables).eqls([ - "q", - ]); - - expect( - me - .fromAst(stateVariables["/d11"].stateValues.formula) - .equals(me.fromText("2 y cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d11"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/d11"].stateValues.derivVariables).eqls([ - "y", - ]); - - expect( - me - .fromAst(stateVariables["/d12"].stateValues.formula) - .equals(me.fromText("2 y cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/d12"].stateValues.variables).eqls([ - "x", - "z", - ]); - expect(stateVariables["/d12"].stateValues.derivVariables).eqls([ - "y", - ]); - - expect( - me - .fromAst(stateVariables["/d13"].stateValues.formula) - .equals(me.fromText("cos(x_1+x_2^2)x_3")), - ).eq(true); - expect(stateVariables["/d13"].stateValues.variables).eqls([ - ["_", "x", 1], - ["_", "x", 2], - ["_", "x", 3], - ]); - expect(stateVariables["/d13"].stateValues.derivVariables).eqls([ - ["_", "x", 1], - ]); - - expect( - me - .fromAst(stateVariables["/d14"].stateValues.formula) - .equals(me.fromText("-sin(x_1+x_2^2)x_3")), - ).eq(true); - expect(stateVariables["/d14"].stateValues.variables).eqls([ - ["_", "x", 1], - ]); - expect(stateVariables["/d14"].stateValues.derivVariables).eqls([ - ["_", "x", 1], - ["_", "x", 1], - ]); - - expect( - me - .fromAst(stateVariables["/d15"].stateValues.formula) - .equals(me.fromText("-sin(x_1+x_2^2)x_3")), - ).eq(true); - expect(stateVariables["/d15"].stateValues.variables).eqls([ - ["_", "x", 1], - ["_", "x", 2], - ["_", "x", 3], - ]); - expect(stateVariables["/d15"].stateValues.derivVariables).eqls([ - ["_", "x", 1], - ["_", "x", 1], - ]); - }); - }); - - it("derivative of function with changed variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - sin(x+y^2)z - $f1 - sin(x_1+x_2^2)x_3 - $g1 - $f1 - $df1 - $f2 - $df2 - $g1 - $dg1 - $g2 - $dg2 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect( - me - .fromAst(stateVariables["/df1"].stateValues.formula) - .equals(me.fromText("cos(x+y^2)z")), - ).eq(true); - expect(stateVariables["/df1"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/df1"].stateValues.derivVariables).eqls([ - "x", - ]); - - expect( - me - .fromAst(stateVariables["/df2"].stateValues.formula) - .equals(me.fromText("sin(x+y^2)")), - ).eq(true); - expect(stateVariables["/df2"].stateValues.variables).eqls([ - "z", - "y", - "x", - ]); - expect(stateVariables["/df2"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/dg1"].stateValues.formula) - .equals(me.fromText("cos(x_1+x_2^2)x_3")), - ).eq(true); - expect(stateVariables["/dg1"].stateValues.variables).eqls([ - ["_", "x", 1], - ["_", "x", 2], - ["_", "x", 3], - ]); - expect(stateVariables["/dg1"].stateValues.derivVariables).eqls([ - ["_", "x", 1], - ]); - - expect( - me - .fromAst(stateVariables["/dg2"].stateValues.formula) - .equals(me.fromText("sin(x_1+x_2^2)")), - ).eq(true); - expect(stateVariables["/dg2"].stateValues.variables).eqls([ - ["_", "x", 3], - ["_", "x", 2], - ["_", "x", 1], - ]); - expect(stateVariables["/dg2"].stateValues.derivVariables).eqls([ - ["_", "x", 3], - ]); - }); - }); - - it("derivative of function with changed variables, convert to single variable function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - sin(x)z - $f1.formula - sin(x)yz - $f3.formula - - $f1 - $f2 - $df2.formula - $f3 - $f3 - $df3y - $f4 - $f4 - $df4z - $df4zy.formula - $df4yz.formula - - - $df2a - - - - $df4zya - - - - $df4yza - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect( - me - .fromAst(stateVariables["/df1"].stateValues.formula) - .equals(me.fromText("sin(x)")), - ).eq(true); - expect(stateVariables["/df1"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/df1"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/df2"].stateValues.formula) - .equals(me.fromText("sin(x)")), - ).eq(true); - expect(stateVariables["/df2"].stateValues.variables).eqls([ - "z", - "y", - "x", - ]); - expect(stateVariables["/df2"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/df2a"].stateValues.formula) - .equals(me.fromText("sin(x)")), - ).eq(true); - expect(stateVariables["/df2a"].stateValues.variables).eqls(["x"]); - - expect( - me - .fromAst(stateVariables["/df3zy"].stateValues.formula) - .equals(me.fromText("sin(x)")), - ).eq(true); - expect(stateVariables["/df3zy"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/df3zy"].stateValues.derivVariables).eqls([ - "z", - "y", - ]); - - expect( - me - .fromAst(stateVariables["/df3y"].stateValues.formula) - .equals(me.fromText("sin(x)z")), - ).eq(true); - expect(stateVariables["/df3y"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/df3y"].stateValues.derivVariables).eqls([ - "y", - ]); - - expect( - me - .fromAst(stateVariables["/df3zya"].stateValues.formula) - .equals(me.fromText("sin(x)")), - ).eq(true); - expect(stateVariables["/df3zya"].stateValues.variables).eqls([ - "x", - "y", - "z", - ]); - expect(stateVariables["/df3zya"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/df4zy"].stateValues.formula) - .equals(me.fromText("sin(x)")), - ).eq(true); - expect(stateVariables["/df4zy"].stateValues.variables).eqls([ - "z", - "y", - "x", - ]); - expect(stateVariables["/df4zy"].stateValues.derivVariables).eqls([ - "z", - "y", - ]); - - expect( - me - .fromAst(stateVariables["/df4z"].stateValues.formula) - .equals(me.fromText("sin(x)y")), - ).eq(true); - expect(stateVariables["/df4z"].stateValues.variables).eqls([ - "z", - "y", - "x", - ]); - expect(stateVariables["/df4z"].stateValues.derivVariables).eqls([ - "z", - ]); - - expect( - me - .fromAst(stateVariables["/df4yz"].stateValues.formula) - .equals(me.fromText("sin(x)")), - ).eq(true); - expect(stateVariables["/df4yz"].stateValues.variables).eqls([ - "z", - "y", - "x", - ]); - expect(stateVariables["/df4yz"].stateValues.derivVariables).eqls([ - "y", - ]); - - expect( - me - .fromAst(stateVariables["/df4zya"].stateValues.formula) - .equals(me.fromText("sin(x)")), - ).eq(true); - expect(stateVariables["/df4zya"].stateValues.variables).eqls(["x"]); - - expect( - me - .fromAst(stateVariables["/df4yza"].stateValues.formula) - .equals(me.fromText("sin(x)")), - ).eq(true); - expect(stateVariables["/df4yza"].stateValues.variables).eqls(["x"]); - - expect(stateVariables["/t1/df1"].stateValues.value).eqls([ - "apply", - "sin", - -2, - ]); - expect(stateVariables["/t1/df2a"].stateValues.value).eqls([ - "apply", - "sin", - -2, - ]); - expect(stateVariables["/t1/df3zy"].stateValues.value).eqls([ - "apply", - "sin", - -2, - ]); - expect(stateVariables["/t1/df3zya"].stateValues.value).eqls([ - "apply", - "sin", - -2, - ]); - expect(stateVariables["/t1/df4zya"].stateValues.value).eqls([ - "apply", - "sin", - -2, - ]); - expect(stateVariables["/t1/df4yza"].stateValues.value).eqls([ - "apply", - "sin", - -2, - ]); - expect(stateVariables["/t1/df1n"].stateValues.value).closeTo( - Math.sin(-2), - 1e-10, - ); - expect(stateVariables["/t1/df2an"].stateValues.value).closeTo( - Math.sin(-2), - 1e-10, - ); - expect(stateVariables["/t1/df3zyn"].stateValues.value).closeTo( - Math.sin(-2), - 1e-10, - ); - expect(stateVariables["/t1/df3zyan"].stateValues.value).closeTo( - Math.sin(-2), - 1e-10, - ); - expect(stateVariables["/t1/df4zyan"].stateValues.value).closeTo( - Math.sin(-2), - 1e-10, - ); - expect(stateVariables["/t1/df4yzan"].stateValues.value).closeTo( - Math.sin(-2), - 1e-10, - ); - - expect(stateVariables["/t2/df1"].stateValues.value).eq(0); - expect(stateVariables["/t2/df2a"].stateValues.value).eq(0); - expect(stateVariables["/t2/df3zy"].stateValues.value).eq(0); - expect(stateVariables["/t2/df3zya"].stateValues.value).eq(0); - expect(stateVariables["/t2/df4zya"].stateValues.value).eq(0); - expect(stateVariables["/t2/df4yza"].stateValues.value).eq(0); - expect(stateVariables["/t2/df1n"].stateValues.value).closeTo( - 0, - 1e-10, - ); - expect(stateVariables["/t2/df2an"].stateValues.value).closeTo( - 0, - 1e-10, - ); - expect(stateVariables["/t2/df3zyn"].stateValues.value).closeTo( - 0, - 1e-10, - ); - expect(stateVariables["/t2/df3zyan"].stateValues.value).closeTo( - 0, - 1e-10, - ); - expect(stateVariables["/t2/df4zyan"].stateValues.value).closeTo( - 0, - 1e-10, - ); - expect(stateVariables["/t2/df4yzan"].stateValues.value).closeTo( - 0, - 1e-10, - ); - - expect(stateVariables["/t3/df1"].stateValues.value).eqls([ - "apply", - "sin", - 2, - ]); - expect(stateVariables["/t3/df2a"].stateValues.value).eqls([ - "apply", - "sin", - 2, - ]); - expect(stateVariables["/t3/df3zy"].stateValues.value).eqls([ - "apply", - "sin", - 2, - ]); - expect(stateVariables["/t3/df3zya"].stateValues.value).eqls([ - "apply", - "sin", - 2, - ]); - expect(stateVariables["/t3/df4zya"].stateValues.value).eqls([ - "apply", - "sin", - 2, - ]); - expect(stateVariables["/t3/df4yza"].stateValues.value).eqls([ - "apply", - "sin", - 2, - ]); - expect(stateVariables["/t3/df1n"].stateValues.value).closeTo( - Math.sin(2), - 1e-10, - ); - expect(stateVariables["/t3/df2an"].stateValues.value).closeTo( - Math.sin(2), - 1e-10, - ); - expect(stateVariables["/t3/df3zyn"].stateValues.value).closeTo( - Math.sin(2), - 1e-10, - ); - expect(stateVariables["/t3/df3zyan"].stateValues.value).closeTo( - Math.sin(2), - 1e-10, - ); - expect(stateVariables["/t3/df4zyan"].stateValues.value).closeTo( - Math.sin(2), - 1e-10, - ); - expect(stateVariables["/t3/df4yzan"].stateValues.value).closeTo( - Math.sin(2), - 1e-10, - ); - - let df1 = createFunctionFromDefinition( - stateVariables["/df1"].stateValues.fDefinitions[0], - ); - let df2a = createFunctionFromDefinition( - stateVariables["/df2a"].stateValues.fDefinitions[0], - ); - let df3zy = createFunctionFromDefinition( - stateVariables["/df3zy"].stateValues.fDefinitions[0], - ); - let df3zya = createFunctionFromDefinition( - stateVariables["/df3zya"].stateValues.fDefinitions[0], - ); - let df4zya = createFunctionFromDefinition( - stateVariables["/df4zya"].stateValues.fDefinitions[0], - ); - let df4yza = createFunctionFromDefinition( - stateVariables["/df4yza"].stateValues.fDefinitions[0], - ); - - for (let i = 1; i <= 21; i++) { - let x = 0.2 * (i - 11); - expect(df1(x, 0, 0)).closeTo(Math.sin(x), 1e-10); - expect(df2a(x)).closeTo(Math.sin(x), 1e-10); - expect(df3zy(x, 0, 0)).closeTo(Math.sin(x), 1e-10); - expect(df3zya(x, 0, 0)).closeTo(Math.sin(x), 1e-10); - expect(df4zya(x)).closeTo(Math.sin(x), 1e-10); - expect(df4yza(x)).closeTo(Math.sin(x), 1e-10); - } - }); - }); - - it("derivative with empty variables attribute", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x^2 - - - $d1 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect( - me - .fromAst(stateVariables["/d1"].stateValues.formula) - .equals(me.fromText("2x")), - ).eq(true); - expect(stateVariables["/d1"].stateValues.variables).eqls(["x"]); - expect(stateVariables["/d1"].stateValues.derivVariables).eqls([ - "x", - ]); - - let d1 = createFunctionFromDefinition( - stateVariables["/d1"].stateValues.fDefinitions[0], - ); - - for (let i = 1; i <= 21; i++) { - let x = 0.2 * (i - 11); - expect(d1(x)).closeTo(2 * x, 1e-10); - } - }); - }); - - it("derivatives of vector-valued functions", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (sin(x), cos(x)) - (e^(2y), y, log(y)) - (xyz, xy, xz, yz) - (xyz, xy, xz, yz) - (x^2, x^3) - (x^2, x^3) - $x2 - $x2 - (x^2sin(z), z^2sin(x)) - (x^2sin(z),z^2sin(x)) - z2 - (x^$a sin($var), $var^$a sin(x)) - $f1 - $f1 - $f2 - $f2 - $f3 - $f3 - $f4 - $f4 - $f1 - $f2 - $f3 - $f4 - $f3 - $f4 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/d1"].stateValues.formula) - .equals(me.fromText("(2x,3x^2)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d2"].stateValues.formula) - .equals(me.fromText("(2x,3x^2)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d2b"].stateValues.formula) - .equals(me.fromText("(2x,3x^2)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d2c"].stateValues.formula) - .equals(me.fromText("(2x,3x^2)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d3"].stateValues.formula) - .equals(me.fromText("(2x sin(z), z^2 cos(x))")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d4"].stateValues.formula) - .equals(me.fromText("(x^2cos(z), 2z sin(x))")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d4b"].stateValues.formula) - .equals(me.fromText("(x^2cos(z), 2z sin(x))")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d5"].stateValues.formula) - .equals(me.fromText("(cos(x),-sin(x))")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d5b"].stateValues.formula) - .equals(me.fromText("(cos(x), -sin(x))")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d6"].stateValues.formula) - .equals(me.fromText("(2e^(2y),1,1/y)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d6b"].stateValues.formula) - .equals(me.fromText("(2e^(2y),1,1/y)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d7"].stateValues.formula) - .equals(me.fromText("(yz, y, z, 0)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d7b"].stateValues.formula) - .equals(me.fromText("(yz, y, z, 0)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d8"].stateValues.formula) - .equals(me.fromText("(xy, 0, x, y)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d8b"].stateValues.formula) - .equals(me.fromText("(xy, 0, x, y)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d9"].stateValues.formula) - .equals(me.fromText("(0,0)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d10"].stateValues.formula) - .equals(me.fromText("(0,0,0)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d11"].stateValues.formula) - .equals(me.fromText("(0,0,0,0)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d12"].stateValues.formula) - .equals(me.fromText("(0,0,0,0)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d13"].stateValues.formula) - .equals(me.fromText("(xz,x,0,z)")), - ).eq(true); - expect( - me - .fromAst(stateVariables["/d14"].stateValues.formula) - .equals(me.fromText("(xz,x,0,z)")), - ).eq(true); - - let d1_1 = createFunctionFromDefinition( - stateVariables["/d1"].stateValues.fDefinitions[0], - ); - let d1_2 = createFunctionFromDefinition( - stateVariables["/d1"].stateValues.fDefinitions[1], - ); - let d2_1 = createFunctionFromDefinition( - stateVariables["/d2"].stateValues.fDefinitions[0], - ); - let d2_2 = createFunctionFromDefinition( - stateVariables["/d2"].stateValues.fDefinitions[1], - ); - let d2b_1 = createFunctionFromDefinition( - stateVariables["/d2b"].stateValues.fDefinitions[0], - ); - let d2b_2 = createFunctionFromDefinition( - stateVariables["/d2b"].stateValues.fDefinitions[1], - ); - let d2c_1 = createFunctionFromDefinition( - stateVariables["/d2c"].stateValues.fDefinitions[0], - ); - let d2c_2 = createFunctionFromDefinition( - stateVariables["/d2c"].stateValues.fDefinitions[1], - ); - let d5_1 = createFunctionFromDefinition( - stateVariables["/d5"].stateValues.fDefinitions[0], - ); - let d5_2 = createFunctionFromDefinition( - stateVariables["/d5"].stateValues.fDefinitions[1], - ); - let d5b_1 = createFunctionFromDefinition( - stateVariables["/d5b"].stateValues.fDefinitions[0], - ); - let d5b_2 = createFunctionFromDefinition( - stateVariables["/d5b"].stateValues.fDefinitions[1], - ); - let d6_1 = createFunctionFromDefinition( - stateVariables["/d6"].stateValues.fDefinitions[0], - ); - let d6_2 = createFunctionFromDefinition( - stateVariables["/d6"].stateValues.fDefinitions[1], - ); - let d6_3 = createFunctionFromDefinition( - stateVariables["/d6"].stateValues.fDefinitions[2], - ); - let d6b_1 = createFunctionFromDefinition( - stateVariables["/d6b"].stateValues.fDefinitions[0], - ); - let d6b_2 = createFunctionFromDefinition( - stateVariables["/d6b"].stateValues.fDefinitions[1], - ); - let d6b_3 = createFunctionFromDefinition( - stateVariables["/d6b"].stateValues.fDefinitions[2], - ); - let d9_1 = createFunctionFromDefinition( - stateVariables["/d9"].stateValues.fDefinitions[0], - ); - let d9_2 = createFunctionFromDefinition( - stateVariables["/d9"].stateValues.fDefinitions[1], - ); - let d10_1 = createFunctionFromDefinition( - stateVariables["/d10"].stateValues.fDefinitions[0], - ); - let d10_2 = createFunctionFromDefinition( - stateVariables["/d10"].stateValues.fDefinitions[1], - ); - let d10_3 = createFunctionFromDefinition( - stateVariables["/d10"].stateValues.fDefinitions[2], - ); - let d11_1 = createFunctionFromDefinition( - stateVariables["/d11"].stateValues.fDefinitions[0], - ); - let d11_2 = createFunctionFromDefinition( - stateVariables["/d11"].stateValues.fDefinitions[1], - ); - let d11_3 = createFunctionFromDefinition( - stateVariables["/d11"].stateValues.fDefinitions[2], - ); - let d11_4 = createFunctionFromDefinition( - stateVariables["/d11"].stateValues.fDefinitions[3], - ); - let d12_1 = createFunctionFromDefinition( - stateVariables["/d12"].stateValues.fDefinitions[0], - ); - let d12_2 = createFunctionFromDefinition( - stateVariables["/d12"].stateValues.fDefinitions[1], - ); - let d12_3 = createFunctionFromDefinition( - stateVariables["/d12"].stateValues.fDefinitions[2], - ); - let d12_4 = createFunctionFromDefinition( - stateVariables["/d12"].stateValues.fDefinitions[3], - ); - - for (let i = 1; i <= 21; i++) { - let x = 0.2 * (i - 11); - expect(d1_1(x)).closeTo(2 * x, 1e-10); - expect(d1_2(x)).closeTo(3 * x ** 2, 1e-10); - expect(d2_1(x)).closeTo(2 * x, 1e-10); - expect(d2_2(x)).closeTo(3 * x ** 2, 1e-10); - expect(d2b_1(x)).closeTo(2 * x, 1e-10); - expect(d2b_2(x)).closeTo(3 * x ** 2, 1e-10); - expect(d2c_1(x)).closeTo(2 * x, 1e-10); - expect(d2c_2(x)).closeTo(3 * x ** 2, 1e-10); - expect(d5_1(x)).closeTo(Math.cos(x), 1e-10); - expect(d5_2(x)).closeTo(-Math.sin(x), 1e-10); - expect(d5b_1(x)).closeTo(Math.cos(x), 1e-10); - expect(d5b_2(x)).closeTo(-Math.sin(x), 1e-10); - expect(d6_1(x)).closeTo(2 * Math.exp(2 * x), 1e-10); - expect(d6_2(x)).closeTo(1, 1e-10); - if (x === 0) { - expect(d6_3(x)).eq(Infinity); - } else { - expect(d6_3(x)).closeTo(1 / x, 1e-10); - } - expect(d6b_1(x)).closeTo(2 * Math.exp(2 * x), 1e-10); - expect(d6b_2(x)).closeTo(1, 1e-10); - if (x === 0) { - expect(d6b_3(x)).eq(Infinity); - } else { - expect(d6b_3(x)).closeTo(1 / x, 1e-10); - } - expect(d9_1(x)).closeTo(0, 1e-10); - expect(d9_2(x)).closeTo(0, 1e-10); - expect(d10_1(x)).closeTo(0, 1e-10); - expect(d10_2(x)).closeTo(0, 1e-10); - expect(d10_3(x)).closeTo(0, 1e-10); - expect(d11_1(x)).closeTo(0, 1e-10); - expect(d11_2(x)).closeTo(0, 1e-10); - expect(d11_3(x)).closeTo(0, 1e-10); - expect(d11_4(x)).closeTo(0, 1e-10); - expect(d12_1(x)).closeTo(0, 1e-10); - expect(d12_2(x)).closeTo(0, 1e-10); - expect(d12_3(x)).closeTo(0, 1e-10); - expect(d12_4(x)).closeTo(0, 1e-10); - } - }); - }); - - // check to make sure fixed bug where wasn't displaying inside - it("derivative displayed inside ", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Let f(x) = sin(x). - Then f'(x) = $f.

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(x)=sin(x)"); - }); - - cy.get(cesc("#\\/_m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f′(x)=cos(x)"); - }); - }); - - it("derivatives of interpolated function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $_function1 - $_derivative1 - $_derivative2 - $_derivative3 - $_derivative4 - $_derivative5 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f1 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - let d1 = createFunctionFromDefinition( - stateVariables["/_derivative1"].stateValues.fDefinitions[0], - ); - let d2 = createFunctionFromDefinition( - stateVariables["/_derivative2"].stateValues.fDefinitions[0], - ); - let d3 = createFunctionFromDefinition( - stateVariables["/_derivative3"].stateValues.fDefinitions[0], - ); - let d4 = createFunctionFromDefinition( - stateVariables["/_derivative4"].stateValues.fDefinitions[0], - ); - let d5 = createFunctionFromDefinition( - stateVariables["/_derivative5"].stateValues.fDefinitions[0], - ); - let d6 = createFunctionFromDefinition( - stateVariables["/_derivative6"].stateValues.fDefinitions[0], - ); - - for (let x = -10; x <= 10; x += 0.5) { - expect(f1(x)).eq((x - 3) ** 2 + 4); - expect(d1(x)).eq(2 * (x - 3)); - expect(d2(x)).eq(2); - expect(d3(x)).eq(0); - expect(d4(x)).eq(0); - expect(d5(x)).eq(0); - expect(d6(x)).eq(0); - } - }); - }); - - it("derivatives of interpolated function 2", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $_function1 - $_derivative1 - $_derivative2 - $_derivative3 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let dx = 0.0001; - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - let d1 = createFunctionFromDefinition( - stateVariables["/_derivative1"].stateValues.fDefinitions[0], - ); - let d2 = createFunctionFromDefinition( - stateVariables["/_derivative2"].stateValues.fDefinitions[0], - ); - let d3 = createFunctionFromDefinition( - stateVariables["/_derivative3"].stateValues.fDefinitions[0], - ); - let d4 = createFunctionFromDefinition( - stateVariables["/_derivative4"].stateValues.fDefinitions[0], - ); - - // make sure we don't get within dx of a grid point - for (let x = -10.02412412; x <= 10; x += 0.5) { - let f0 = f(x); - let f1 = f(x + dx); - let fp05 = d1(x + dx / 2); - expect(fp05).closeTo((f1 - f0) / dx, 1e-6); - - let fpn05 = d1(x - dx / 2); - let fpp0 = d2(x); - expect(fpp0).closeTo((fp05 - fpn05) / dx, 1e-6); - - let fpp1 = d2(x + dx); - let fppp05 = d3(x + dx / 2); - expect(fppp05).closeTo((fpp1 - fpp0) / dx, 1e-6); - - let fpppn05 = d3(x - dx / 2); - let fpppp0 = d4(x); - expect(fpppp0).closeTo((fppp05 - fpppn05) / dx, 1e-6); - } - }); - }); - - it("derivatives of interpolated function that is not a function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $f - - - f(3) = $$f(3) - f'(3) = $$df(3) - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "f(3)=NaN"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "f′(3)=NaN"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f = createFunctionFromDefinition( - stateVariables["/f"].stateValues.fDefinitions[0], - ); - let df = createFunctionFromDefinition( - stateVariables["/df"].stateValues.fDefinitions[0], - ); - expect(f(3)).eqls(NaN); - expect(df(3)).eqls(NaN); - }); - }); - - it("derivatives of interpolated function specified with variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $f - $g - - $f - $g - - $f - $g - - $f - $g - - $f - $g - - $f - $g - - $f - $g - - $f - $g - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let dx = 0.0001; - - let f = createFunctionFromDefinition( - stateVariables["/f"].stateValues.fDefinitions[0], - ); - let df1 = createFunctionFromDefinition( - stateVariables["/df1"].stateValues.fDefinitions[0], - ); - let df1b = createFunctionFromDefinition( - stateVariables["/df1b"].stateValues.fDefinitions[0], - ); - let df2 = createFunctionFromDefinition( - stateVariables["/df2"].stateValues.fDefinitions[0], - ); - let df3 = createFunctionFromDefinition( - stateVariables["/df3"].stateValues.fDefinitions[0], - ); - let df4 = createFunctionFromDefinition( - stateVariables["/df4"].stateValues.fDefinitions[0], - ); - let g = createFunctionFromDefinition( - stateVariables["/g"].stateValues.fDefinitions[0], - ); - let dg1 = createFunctionFromDefinition( - stateVariables["/dg1"].stateValues.fDefinitions[0], - ); - let dg1b = createFunctionFromDefinition( - stateVariables["/dg1b"].stateValues.fDefinitions[0], - ); - let dg2 = createFunctionFromDefinition( - stateVariables["/dg2"].stateValues.fDefinitions[0], - ); - let dg3 = createFunctionFromDefinition( - stateVariables["/dg3"].stateValues.fDefinitions[0], - ); - let dg4 = createFunctionFromDefinition( - stateVariables["/dg4"].stateValues.fDefinitions[0], - ); - let zero1 = createFunctionFromDefinition( - stateVariables["/zero1"].stateValues.fDefinitions[0], - ); - let zero2 = createFunctionFromDefinition( - stateVariables["/zero2"].stateValues.fDefinitions[0], - ); - let zero3 = createFunctionFromDefinition( - stateVariables["/zero3"].stateValues.fDefinitions[0], - ); - let zero4 = createFunctionFromDefinition( - stateVariables["/zero4"].stateValues.fDefinitions[0], - ); - let zero5 = createFunctionFromDefinition( - stateVariables["/zero5"].stateValues.fDefinitions[0], - ); - let zero6 = createFunctionFromDefinition( - stateVariables["/zero6"].stateValues.fDefinitions[0], - ); - - // make sure we don't get within dx of a grid point - for (let x = -10.02412412; x <= 10; x += 0.5) { - let f_0 = f(x); - let f_1 = f(x + dx); - let df1_05 = df1(x + dx / 2); - let df1b_05 = df1b(x + dx / 2); - expect(df1_05).closeTo((f_1 - f_0) / dx, 1e-6); - expect(df1b_05).eq(df1_05); - - let g_0 = g(x); - let g_1 = g(x + dx); - let dg1_05 = dg1(x + dx / 2); - let dg1b_05 = dg1b(x + dx / 2); - expect(dg1_05).closeTo((g_1 - g_0) / dx, 1e-6); - expect(dg1b_05).eq(dg1_05); - - let df1_n05 = df1(x - dx / 2); - let df2_0 = df2(x); - expect(df2_0).closeTo((df1b_05 - df1_n05) / dx, 1e-6); - - let dg1_n05 = dg1(x - dx / 2); - let dg2_0 = dg2(x); - expect(dg2_0).closeTo((dg1b_05 - dg1_n05) / dx, 1e-6); - - let df2_1 = df2(x + dx); - let df3_05 = df3(x + dx / 2); - expect(df3_05).closeTo((df2_1 - df2_0) / dx, 1e-6); - - let dg2_1 = dg2(x + dx); - let dg3_05 = dg3(x + dx / 2); - expect(dg3_05).closeTo((dg2_1 - dg2_0) / dx, 1e-6); - - let df3_n05 = df3(x - dx / 2); - let df4_0 = df4(x); - expect(df4_0).closeTo((df3_05 - df3_n05) / dx, 1e-6); - - let dg3_n05 = dg3(x - dx / 2); - let dg4_0 = dg4(x); - expect(dg4_0).closeTo((dg3_05 - dg3_n05) / dx, 1e-6); - - expect(zero1(x)).eq(0); - expect(zero2(x)).eq(0); - expect(zero3(x)).eq(0); - expect(zero4(x)).eq(0); - expect(zero5(x)).eq(0); - expect(zero6(x)).eq(0); - } - }); - }); - - it("derivatives of interpolated function with changed variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - $f - $g - - $f - $g - $h - - $f - $g - $h - - $f - $g - $h - - $f - $g - $h - - $f - $g - $h - - $f - $g - $h - - $f - $g - $h - - $f - $g - $h - - $f - $g - $h - - $f - $g - $h - - 0.0001 - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let dx = 0.0001; - - let f = createFunctionFromDefinition( - stateVariables["/f"].stateValues.fDefinitions[0], - ); - let df1 = createFunctionFromDefinition( - stateVariables["/df1"].stateValues.fDefinitions[0], - ); - let df1b = createFunctionFromDefinition( - stateVariables["/df1b"].stateValues.fDefinitions[0], - ); - let df2 = createFunctionFromDefinition( - stateVariables["/df2"].stateValues.fDefinitions[0], - ); - let df2b = createFunctionFromDefinition( - stateVariables["/df2b"].stateValues.fDefinitions[0], - ); - let df3 = createFunctionFromDefinition( - stateVariables["/df3"].stateValues.fDefinitions[0], - ); - let df4 = createFunctionFromDefinition( - stateVariables["/df4"].stateValues.fDefinitions[0], - ); - let g = createFunctionFromDefinition( - stateVariables["/g"].stateValues.fDefinitions[0], - ); - let dg1 = createFunctionFromDefinition( - stateVariables["/dg1"].stateValues.fDefinitions[0], - ); - let dg1b = createFunctionFromDefinition( - stateVariables["/dg1b"].stateValues.fDefinitions[0], - ); - let dg2 = createFunctionFromDefinition( - stateVariables["/dg2"].stateValues.fDefinitions[0], - ); - let dg2b = createFunctionFromDefinition( - stateVariables["/dg2b"].stateValues.fDefinitions[0], - ); - let dg3 = createFunctionFromDefinition( - stateVariables["/dg3"].stateValues.fDefinitions[0], - ); - let dg4 = createFunctionFromDefinition( - stateVariables["/dg4"].stateValues.fDefinitions[0], - ); - let h = createFunctionFromDefinition( - stateVariables["/h"].stateValues.fDefinitions[0], - ); - let dh1 = createFunctionFromDefinition( - stateVariables["/dh1"].stateValues.fDefinitions[0], - ); - let dh1b = createFunctionFromDefinition( - stateVariables["/dh1b"].stateValues.fDefinitions[0], - ); - let dh2 = createFunctionFromDefinition( - stateVariables["/dh2"].stateValues.fDefinitions[0], - ); - let dh2b = createFunctionFromDefinition( - stateVariables["/dh2b"].stateValues.fDefinitions[0], - ); - let dh3 = createFunctionFromDefinition( - stateVariables["/dh3"].stateValues.fDefinitions[0], - ); - let dh4 = createFunctionFromDefinition( - stateVariables["/dh4"].stateValues.fDefinitions[0], - ); - let zero1 = createFunctionFromDefinition( - stateVariables["/zero1"].stateValues.fDefinitions[0], - ); - let zero2 = createFunctionFromDefinition( - stateVariables["/zero2"].stateValues.fDefinitions[0], - ); - let zero3 = createFunctionFromDefinition( - stateVariables["/zero3"].stateValues.fDefinitions[0], - ); - let zero4 = createFunctionFromDefinition( - stateVariables["/zero4"].stateValues.fDefinitions[0], - ); - let zero5 = createFunctionFromDefinition( - stateVariables["/zero5"].stateValues.fDefinitions[0], - ); - let zero6 = createFunctionFromDefinition( - stateVariables["/zero6"].stateValues.fDefinitions[0], - ); - let zero7 = createFunctionFromDefinition( - stateVariables["/zero7"].stateValues.fDefinitions[0], - ); - let zero8 = createFunctionFromDefinition( - stateVariables["/zero8"].stateValues.fDefinitions[0], - ); - let zero9 = createFunctionFromDefinition( - stateVariables["/zero9"].stateValues.fDefinitions[0], - ); - let zero10 = createFunctionFromDefinition( - stateVariables["/zero10"].stateValues.fDefinitions[0], - ); - let zero11 = createFunctionFromDefinition( - stateVariables["/zero11"].stateValues.fDefinitions[0], - ); - let zero12 = createFunctionFromDefinition( - stateVariables["/zero12"].stateValues.fDefinitions[0], - ); - - let i = 0; - - // make sure we don't get within dx of a grid point - for (let x = -10.02412412; x <= 10; x += 3.1) { - i++; - - let f_0 = f(x); - let f_1 = f(x + dx); - let df1_05 = df1(x + dx / 2); - let df1b_05 = df1b(x + dx / 2); - expect(df1_05).closeTo((f_1 - f_0) / dx, 1e-6); - expect(df1b_05).eq(df1_05); - - let f_0a = stateVariables[`/t${i}/f_0`].stateValues.value; - expect(f_0a).closeTo(f_0, 1e-10); - let df1_05a = stateVariables[`/t${i}/df1_05`].stateValues.value; - expect(df1_05a).closeTo(df1_05, 1e-10); - let df1b_05a = - stateVariables[`/t${i}/df1b_05`].stateValues.value; - expect(df1b_05a).closeTo(df1b_05, 1e-10); - - let g_0 = g(x); - let g_1 = g(x + dx); - expect(g_0).eq(f_0); - expect(g_1).eq(f_1); - let dg1_05 = dg1(x + dx / 2); - let dg1b_05 = dg1b(x + dx / 2); - expect(dg1_05).closeTo((g_1 - g_0) / dx, 1e-6); - expect(dg1b_05).eq(dg1_05); - - let g_0a = stateVariables[`/t${i}/g_0`].stateValues.value; - expect(g_0a).closeTo(f_0, 1e-10); - let dg1_05a = stateVariables[`/t${i}/dg1_05`].stateValues.value; - expect(dg1_05a).closeTo(df1_05, 1e-10); - let dg1b_05a = - stateVariables[`/t${i}/dg1b_05`].stateValues.value; - expect(dg1b_05a).closeTo(df1b_05, 1e-10); - - let h_0 = h(x); - let h_1 = h(x + dx); - expect(h_0).eq(f_0); - expect(h_1).eq(f_1); - let dh1_05 = dh1(x + dx / 2); - let dh1b_05 = dh1b(x + dx / 2); - expect(dh1_05).closeTo((h_1 - h_0) / dx, 1e-6); - expect(dh1b_05).eq(dh1_05); - - let h_0a = stateVariables[`/t${i}/h_0`].stateValues.value; - expect(h_0a).closeTo(f_0, 1e-10); - let dh1_05a = stateVariables[`/t${i}/dh1_05`].stateValues.value; - expect(dh1_05a).closeTo(df1_05, 1e-10); - let dh1b_05a = - stateVariables[`/t${i}/dh1b_05`].stateValues.value; - expect(dh1b_05a).closeTo(df1b_05, 1e-10); - - let df1_n05 = df1(x - dx / 2); - let df2_0 = df2(x); - expect(df2_0).closeTo((df1b_05 - df1_n05) / dx, 1e-6); - - let df2_0a = stateVariables[`/t${i}/df2_0`].stateValues.value; - expect(df2_0a).closeTo(df2_0, 1e-10); - - let dg2_0 = dg2(x); - expect(dg2_0).eq(df2_0); - - let dg2_0a = stateVariables[`/t${i}/dg2_0`].stateValues.value; - expect(dg2_0a).closeTo(df2_0, 1e-10); - - let dh2_0 = dh2(x); - expect(dh2_0).eq(df2_0); - - let dh2_0a = stateVariables[`/t${i}/dh2_0`].stateValues.value; - expect(dh2_0a).closeTo(df2_0, 1e-10); - - let df2b_0 = df2b(x); - expect(df2b_0).eq(df2_0); - - let df2b_0a = stateVariables[`/t${i}/df2b_0`].stateValues.value; - expect(df2b_0a).closeTo(df2b_0, 1e-10); - - let dg2b_0 = dg2b(x); - expect(dg2b_0).eq(dg2_0); - - let dg2b_0a = stateVariables[`/t${i}/dg2b_0`].stateValues.value; - expect(dg2b_0a).closeTo(df2b_0, 1e-10); - - let dh2b_0 = dh2b(x); - expect(dh2b_0).eq(dh2_0); - - let dh2b_0a = stateVariables[`/t${i}/dh2b_0`].stateValues.value; - expect(dh2b_0a).closeTo(df2b_0, 1e-10); - - let df2_1 = df2(x + dx); - let df3_05 = df3(x + dx / 2); - expect(df3_05).closeTo((df2_1 - df2_0) / dx, 1e-6); - - let df3_05a = stateVariables[`/t${i}/df3_05`].stateValues.value; - expect(df3_05a).closeTo(df3_05, 1e-10); - - let dg3_05 = dg3(x + dx / 2); - expect(dg3_05).eq(df3_05); - - let dg3_05a = stateVariables[`/t${i}/dg3_05`].stateValues.value; - expect(dg3_05a).closeTo(df3_05, 1e-10); - - let dh3_05 = dh3(x + dx / 2); - expect(dh3_05).eq(df3_05); - - let dh3_05a = stateVariables[`/t${i}/dh3_05`].stateValues.value; - expect(dh3_05a).closeTo(df3_05, 1e-10); - - let df3_n05 = df3(x - dx / 2); - let df4_0 = df4(x); - expect(df4_0).closeTo((df3_05 - df3_n05) / dx, 1e-6); - - let df4_0a = stateVariables[`/t${i}/df4_0`].stateValues.value; - expect(df4_0a).closeTo(df4_0, 1e-10); - - let dg4_0 = dg4(x); - expect(dg4_0).eq(df4_0); - - let dg4_0a = stateVariables[`/t${i}/dg4_0`].stateValues.value; - expect(dg4_0a).closeTo(df4_0, 1e-10); - - let dh4_0 = dh4(x); - expect(dh4_0).eq(df4_0); - - let dh4_0a = stateVariables[`/t${i}/dh4_0`].stateValues.value; - expect(dh4_0a).closeTo(df4_0, 1e-10); - - expect(zero1(x)).eq(0); - expect(zero2(x)).eq(0); - expect(zero3(x)).eq(0); - expect(zero4(x)).eq(0); - expect(zero5(x)).eq(0); - expect(zero6(x)).eq(0); - expect(zero7(x)).eq(0); - expect(zero8(x)).eq(0); - expect(zero9(x)).eq(0); - expect(zero10(x)).eq(0); - expect(zero11(x)).eq(0); - expect(zero12(x)).eq(0); - } - }); - }); - - it("derivatives of interpolated function with changed variables, subscript", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - $f - - $f - $g - - $f - $g - - $f - $g - - $f - $g - - $f - $g - - $f - $g - - $f - $g - - $f - $g - - $f - $g - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let dx = 0.0001; - - let f = createFunctionFromDefinition( - stateVariables["/f"].stateValues.fDefinitions[0], - ); - let df1 = createFunctionFromDefinition( - stateVariables["/df1"].stateValues.fDefinitions[0], - ); - let df1b = createFunctionFromDefinition( - stateVariables["/df1b"].stateValues.fDefinitions[0], - ); - let df2 = createFunctionFromDefinition( - stateVariables["/df2"].stateValues.fDefinitions[0], - ); - let df2b = createFunctionFromDefinition( - stateVariables["/df2b"].stateValues.fDefinitions[0], - ); - let df3 = createFunctionFromDefinition( - stateVariables["/df3"].stateValues.fDefinitions[0], - ); - let df4 = createFunctionFromDefinition( - stateVariables["/df4"].stateValues.fDefinitions[0], - ); - let g = createFunctionFromDefinition( - stateVariables["/g"].stateValues.fDefinitions[0], - ); - let dg1 = createFunctionFromDefinition( - stateVariables["/dg1"].stateValues.fDefinitions[0], - ); - let dg1b = createFunctionFromDefinition( - stateVariables["/dg1b"].stateValues.fDefinitions[0], - ); - let dg2 = createFunctionFromDefinition( - stateVariables["/dg2"].stateValues.fDefinitions[0], - ); - let dg2b = createFunctionFromDefinition( - stateVariables["/dg2b"].stateValues.fDefinitions[0], - ); - let dg3 = createFunctionFromDefinition( - stateVariables["/dg3"].stateValues.fDefinitions[0], - ); - let dg4 = createFunctionFromDefinition( - stateVariables["/dg4"].stateValues.fDefinitions[0], - ); - let zero1 = createFunctionFromDefinition( - stateVariables["/zero1"].stateValues.fDefinitions[0], - ); - let zero2 = createFunctionFromDefinition( - stateVariables["/zero2"].stateValues.fDefinitions[0], - ); - let zero3 = createFunctionFromDefinition( - stateVariables["/zero3"].stateValues.fDefinitions[0], - ); - let zero4 = createFunctionFromDefinition( - stateVariables["/zero4"].stateValues.fDefinitions[0], - ); - let zero5 = createFunctionFromDefinition( - stateVariables["/zero5"].stateValues.fDefinitions[0], - ); - let zero6 = createFunctionFromDefinition( - stateVariables["/zero6"].stateValues.fDefinitions[0], - ); - - // make sure we don't get within dx of a grid point - for (let x = -10.02412412; x <= 10; x += 0.5) { - let f_0 = f(x); - let f_1 = f(x + dx); - let df1_05 = df1(x + dx / 2); - let df1b_05 = df1b(x + dx / 2); - expect(df1_05).closeTo((f_1 - f_0) / dx, 1e-6); - expect(df1b_05).eq(df1_05); - - let dg1_05 = dg1(x + dx / 2); - let dg1b_05 = dg1b(x + dx / 2); - expect(dg1_05).eq(dg1_05); - expect(dg1b_05).eq(dg1_05); - - let df1_n05 = df1(x - dx / 2); - let df2_0 = df2(x); - expect(df2_0).closeTo((df1b_05 - df1_n05) / dx, 1e-6); - - let dg2_0 = dg2(x); - expect(dg2_0).eq(df2_0); - - let df2b_0 = df2b(x); - expect(df2b_0).eq(df2_0); - - let dg2b_0 = dg2b(x); - expect(dg2b_0).eq(dg2_0); - - let df2_1 = df2(x + dx); - let df3_05 = df3(x + dx / 2); - expect(df3_05).closeTo((df2_1 - df2_0) / dx, 1e-6); - - let dg3_05 = dg3(x + dx / 2); - expect(dg3_05).eq(df3_05); - - let df3_n05 = df3(x - dx / 2); - let df4_0 = df4(x); - expect(df4_0).closeTo((df3_05 - df3_n05) / dx, 1e-6); - - let dg4_0 = dg4(x); - expect(dg4_0).eq(df4_0); - - expect(zero1(x)).eq(0); - expect(zero2(x)).eq(0); - expect(zero3(x)).eq(0); - expect(zero4(x)).eq(0); - expect(zero5(x)).eq(0); - expect(zero6(x)).eq(0); - } - }); - }); - - it("extrema of derivative", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

c_1 =

-

c_2 =

-

c_3 =

-

c_4 =

-

c_5 =

-

c_6 =

-

x =

- - - $c_1 $x^5/20 - $c_1($c_2+$c_3+$c_4) $x^4/12 - + $c_1($c_2*$c_3 + $c_2 $c_4 + $c_3$c_4)$x^3/6 - - $c_1$c_2$c_3$c_4$x^2/2 + $c_5$x + $c_6 - - -

f($x) = - $formula -

- -

f'($x) = - $f -

- -

again, f'($x) = $fp{name="fp2"} -

- - -

Number of minima of f':

-

Minima of f': $fp.minima

- -

Number of maxima of f':

-

Maxima of f': $fp.maxima

- -

To repeat:

-

Number of minima of f':

-

Minima of f': $fp2.minima

- -

Number of maxima of f':

-

Maxima of f': $fp2.maxima

- - -

- $c_1.value{assignNames="c_1a"} - $c_2.value{assignNames="c_2a"} - $c_3.value{assignNames="c_3a"} - $c_4.value{assignNames="c_4a"} - $c_5.value{assignNames="c_5a"} - $c_6.value{assignNames="c_6a"} - $x.value{assignNames="xa"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - function fp(x, c1, c2, c3, c4, c5) { - return ( - (c1 * x ** 4) / 4 - - (c1 * (c2 + c3 + c4) * x ** 3) / 3 + - (c1 * (c2 * c3 + c2 * c4 + c3 * c4) * x ** 2) / 2 - - c1 * c2 * c3 * c4 * x + - c5 - ); - } - - function fpMinima(c1, c2, c3, c4, c5) { - let extrema = [c2, c3, c4].sort((a, b) => a - b); - let minima = []; - if (c1 > 0) { - minima.push([extrema[0], fp(extrema[0], c1, c2, c3, c4, c5)]); - minima.push([extrema[2], fp(extrema[2], c1, c2, c3, c4, c5)]); - } else { - minima.push([extrema[1], fp(extrema[1], c1, c2, c3, c4, c5)]); - } - return minima; - } - - function fpMaxima(c1, c2, c3, c4, c5) { - let extrema = [c2, c3, c4].sort((a, b) => a - b); - let maxima = []; - if (c1 > 0) { - maxima.push([extrema[1], fp(extrema[1], c1, c2, c3, c4, c5)]); - } else { - maxima.push([extrema[0], fp(extrema[0], c1, c2, c3, c4, c5)]); - maxima.push([extrema[2], fp(extrema[2], c1, c2, c3, c4, c5)]); - } - return maxima; - } - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - function verifyExtrema(c1, c2, c3, c4, c5) { - let minima = fpMinima(c1, c2, c3, c4, c5); - let nMinima = minima.length; - let maxima = fpMaxima(c1, c2, c3, c4, c5); - let nMaxima = maxima.length; - - expect(stateVariables[""]); - - cy.get(cesc("#\\/nMinima")).should( - "have.text", - nMinima.toString(), - ); - cy.get(cesc("#\\/nMinima2")).should( - "have.text", - nMinima.toString(), - ); - cy.get(cesc("#\\/min1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${minima[0][0]},${me.math.round( - minima[0][1], - 5, - )})`, - ); - }); - cy.get(cesc("#\\/min12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${minima[0][0]},${me.math.round( - minima[0][1], - 5, - )})`, - ); - }); - if (nMinima === 2) { - cy.get(cesc("#\\/min2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${minima[1][0]},${me.math.round( - minima[1][1], - 5, - )})`, - ); - }); - cy.get(cesc("#\\/min22")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${minima[1][0]},${me.math.round( - minima[1][1], - 5, - )})`, - ); - }); - } else { - cy.get(cesc("#\\/min2")).should("not.exist"); - cy.get(cesc("#\\/min22")).should("not.exist"); - } - cy.get(cesc("#\\/nMaxima")).should( - "have.text", - nMaxima.toString(), - ); - cy.get(cesc("#\\/nMaxima2")).should( - "have.text", - nMaxima.toString(), - ); - cy.get(cesc("#\\/max1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${maxima[0][0]},${me.math.round( - maxima[0][1], - 5, - )})`, - ); - }); - cy.get(cesc("#\\/max12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${maxima[0][0]},${me.math.round( - maxima[0][1], - 5, - )})`, - ); - }); - if (nMaxima === 2) { - cy.get(cesc("#\\/max2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${maxima[1][0]},${me.math.round( - maxima[1][1], - 5, - )})`, - ); - }); - cy.get(cesc("#\\/max22")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${maxima[1][0]},${me.math.round( - maxima[1][1], - 5, - )})`, - ); - }); - } else { - cy.get(cesc("#\\/max2")).should("not.exist"); - cy.get(cesc("#\\/max22")).should("not.exist"); - } - } - - let c1 = 1, - c2 = 1, - c3 = 3, - c4 = 4, - c5 = 5, - c6 = 1, - v = "x"; - - verifyExtrema(c1, c2, c3, c4, c5); - - cy.window().then(async (win) => { - c1 = 3; - cy.get(cesc2("#/c_1") + " textarea").type( - `{end}{backspace}{backspace}${c1}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/c_1a")).should("contain.text", nInDOM(c1)); - verifyExtrema(c1, c2, c3, c4, c5); - - c2 = -5; - cy.get(cesc2("#/c_2") + " textarea").type( - `{end}{backspace}{backspace}${c2}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/c_2a")).should("contain.text", nInDOM(c2)); - verifyExtrema(c1, c2, c3, c4, c5); - - c3 = 1; - cy.get(cesc2("#/c_3") + " textarea").type( - `{end}{backspace}{backspace}${c3}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/c_3a")).should("contain.text", nInDOM(c3)); - verifyExtrema(c1, c2, c3, c4, c5); - - c4 = -6; - cy.get(cesc2("#/c_4") + " textarea").type( - `{end}{backspace}{backspace}${c4}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/c_4a")).should("contain.text", nInDOM(c4)); - verifyExtrema(c1, c2, c3, c4, c5); - - c5 = 3; - cy.get(cesc2("#/c_5") + " textarea").type( - `{end}{backspace}{backspace}${c5}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/c_5a")).should("contain.text", nInDOM(c5)); - verifyExtrema(c1, c2, c3, c4, c5); - - c6 = 2; - cy.get(cesc2("#/c_6") + " textarea").type( - `{end}{backspace}{backspace}${c6}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/c_6a")).should("contain.text", nInDOM(c6)); - verifyExtrema(c1, c2, c3, c4, c5); - - v = "y"; - cy.get(cesc2("#/x") + " textarea").type( - `{end}{backspace}{backspace}${v}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/xa")).should("contain.text", v); - verifyExtrema(c1, c2, c3, c4, c5); - }); - - cy.window().then(async (win) => { - c1 = 2; - cy.get(cesc2("#/c_1") + " textarea").type( - `{end}{backspace}{backspace}${c1}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/c_1a")).should("contain.text", nInDOM(c1)); - verifyExtrema(c1, c2, c3, c4, c5); - - c2 = 4; - cy.get(cesc2("#/c_2") + " textarea").type( - `{end}{backspace}{backspace}${c2}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/c_2a")).should("contain.text", nInDOM(c2)); - verifyExtrema(c1, c2, c3, c4, c5); - - c3 = -8; - cy.get(cesc2("#/c_3") + " textarea").type( - `{end}{backspace}{backspace}${c3}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/c_3a")).should("contain.text", nInDOM(c3)); - verifyExtrema(c1, c2, c3, c4, c5); - - c4 = 9; - cy.get(cesc2("#/c_4") + " textarea").type( - `{end}{backspace}{backspace}${c4}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/c_4a")).should("contain.text", nInDOM(c4)); - verifyExtrema(c1, c2, c3, c4, c5); - - c5 = -2; - cy.get(cesc2("#/c_5") + " textarea").type( - `{end}{backspace}{backspace}${c5}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/c_5a")).should("contain.text", nInDOM(c5)); - verifyExtrema(c1, c2, c3, c4, c5); - - c6 = 6; - cy.get(cesc2("#/c_6") + " textarea").type( - `{end}{backspace}{backspace}${c6}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/c_6a")).should("contain.text", nInDOM(c6)); - verifyExtrema(c1, c2, c3, c4, c5); - - v = "q"; - cy.get(cesc2("#/x") + " textarea").type( - `{end}{backspace}{backspace}${v}{enter}`, - { force: true }, - ); - cy.get(cesc2("#/xa")).should("contain.text", v); - verifyExtrema(c1, c2, c3, c4, c5); - }); - }); - }); - - it("extrema of derivative of interpolated function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $f - - - $fp{name="fp2"} - -

Number of minima of f':

-

Minima of f': $fp.minima

- -

Number of maxima of f':

-

Maxima of f': $fp.maxima

- -

To repeat:

-

Number of minima of f':

-

Minima of f': $fp2.minima

- -

Number of maxima of f':

-

Maxima of f': $fp2.maxima

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/nMinima")).should("have.text", "1"); - cy.get(cesc("#\\/nMinima2")).should("have.text", "1"); - - cy.get(cesc("#\\/nMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/nMaxima2")).should("have.text", "2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let fp = createFunctionFromDefinition( - stateVariables["/fp"].stateValues.fDefinitions[0], - ); - - let max1x = (-5 - 3) / 2; - cy.get(cesc("#\\/max1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${max1x},${me.math.round(fp(max1x), 5)})`, - ); - }); - cy.get(cesc("#\\/max12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${max1x},${me.math.round(fp(max1x), 5)})`, - ); - }); - - let min1x = (-3 + 0) / 2; - cy.get(cesc("#\\/min1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${min1x},${me.math.round(fp(min1x), 5)})`, - ); - }); - cy.get(cesc("#\\/min12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${min1x},${me.math.round(fp(min1x), 5)})`, - ); - }); - - let max2x = (0 + 6) / 2; - cy.get(cesc("#\\/max2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${max2x},${me.math.round(fp(max2x), 5)})`, - ); - }); - cy.get(cesc("#\\/max22")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - `(${max2x},${me.math.round(fp(max2x), 5)})`, - ); - }); - }); - }); - - it("handle no child", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - $nothing - -

$$d1(0)

-

$$d2(0)

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/d1") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/d2") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "NaN"); - cy.get(cesc("#\\/_p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "NaN"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let d1 = createFunctionFromDefinition( - stateVariables["/d1"].stateValues.fDefinitions[0], - ); - let d2 = createFunctionFromDefinition( - stateVariables["/d2"].stateValues.fDefinitions[0], - ); - - expect(d1(0)).eqls(NaN); - expect(d2(0)).eqls(NaN); - }); - }); -});