diff --git a/packages/doenetml-worker/src/components/dynamicalSystems/ODESystem.js b/packages/doenetml-worker/src/components/dynamicalSystems/ODESystem.js index bddbaba9e..d47d3bf92 100644 --- a/packages/doenetml-worker/src/components/dynamicalSystems/ODESystem.js +++ b/packages/doenetml-worker/src/components/dynamicalSystems/ODESystem.js @@ -558,7 +558,7 @@ export default class ODESystem extends InlineComponent { }, }), definition({ dependencyValues }) { - console.log(dependencyValues); + // console.log(dependencyValues); let warnings = []; let valid = true; diff --git a/packages/doenetml-worker/src/test/dynamicalsystem/cobwebpolyline.test.ts b/packages/doenetml-worker/src/test/dynamicalsystem/cobwebpolyline.test.ts new file mode 100644 index 000000000..e0581a4a9 --- /dev/null +++ b/packages/doenetml-worker/src/test/dynamicalsystem/cobwebpolyline.test.ts @@ -0,0 +1,407 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { + movePolyline, + submitAnswer, + updateMathInputValue, + updateValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); +vi.mock("hyperformula"); + +describe("CobwebPolyline Tag Tests", async () => { + it("logistic system", async () => { + let core = await createTestCore({ + doenetML: ` + 1/3*x*(3-x)+x + 1 + + + + + + + + +

Initial condition is x_0 = 1: + + + $P1.coords = (1,0) + + +

+ + + + + + + + + + x_n + x_{n+1} + + + + + + Result of cobweb sketch + + + + + + $(graph1/cobweb.iterateValues) + + + + + + +

Cobweb at least three iterations

+

+ true + + $(graph1/cobweb.vertices) + + +

+ +

Submitted responses are the vertices of the polyline: $check_cobweb.submittedResponses{displayDigits="5"}

+

Current responses are the vertices of the polyline: $check_cobweb.currentResponses{displayDigits="5"}

+ `, + }); + + let latexResults = ["x_{ 0 } & = -1.5"]; + let submittedVertices: string[] = []; + let currentVertices = ["( -1.5, 0 )"]; + let initialValCredit = 0; + let cobwebCredit = 0; + let cobwebJustSubmitted = false; + + async function check_items() { + let stateVariables = await returnAllStateVariables(core); + // check scores + expect( + stateVariables["/check_initial"].stateValues.creditAchieved, + ).eqls(initialValCredit); + expect( + stateVariables["/check_cobweb"].stateValues.creditAchieved, + ).eqls(cobwebCredit); + expect( + stateVariables["/check_cobweb"].stateValues.justSubmitted, + ).eqls(cobwebJustSubmitted); + // check numPoints + expect(stateVariables["/numPoints"].stateValues.value).eqls( + currentVertices.length, + ); + // check math rows + let mdChildren = stateVariables["/md1"].activeChildren; + expect(mdChildren.length).eqls(latexResults.length); + for (let i = 0; i < latexResults.length; i++) { + let childName = mdChildren[i].componentName; + expect(stateVariables[childName].stateValues.latex).eqls( + latexResults[i], + ); + } + // check submitted vertices via paragraph + let allSubmittedVertices = submittedVertices.reduce( + (a, v) => `${a}, ${v}`, + "", + ); + if (allSubmittedVertices.length > 0) { + allSubmittedVertices = allSubmittedVertices.substring(2); + } + expect(stateVariables["/psr"].stateValues.text).eqls( + `Submitted responses are the vertices of the polyline: ${allSubmittedVertices}`, + ); + + // check submitted vertices via paragraph + let allCurrentVertices = currentVertices.reduce( + (a, v) => `${a}, ${v}`, + "", + ); + if (allCurrentVertices.length > 0) { + allCurrentVertices = allCurrentVertices.substring(2); + } + expect(stateVariables["/pcr"].stateValues.text).eqls( + `Current responses are the vertices of the polyline: ${allCurrentVertices}`, + ); + } + + await check_items(); + // Also check can't remove line + { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/deleteline"].stateValues.hidden).eqls(true); + } + + // Click both submit buttons + submittedVertices = [...currentVertices]; + cobwebJustSubmitted = true; + await submitAnswer({ name: "/check_initial", core }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Move first point + currentVertices[0] = "( 1, 0 )"; + latexResults[0] = "x_{ 0 } & = 1"; + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 0: [1, 0] }, + core, + }); + await check_items(); + + // Click initial value submit + initialValCredit = 1; + await submitAnswer({ name: "/check_initial", core }); + await check_items(); + + // Add second point, should spawn at center of graph + const graphCenterX = (-2 + 5) / 2; + const graphCenterY = (-2.2 + 4.5) / 2; + latexResults.push(`x_{ 1 } & = ${graphCenterY}`); + currentVertices.push(`( ${graphCenterX}, ${graphCenterY} )`); + cobwebJustSubmitted = false; + await updateValue({ name: "/addline", core }); + await check_items(); + + // Move second point to wrong location, submit + latexResults[1] = "x_{ 1 } & = 4"; + currentVertices[1] = "( 3, 4 )"; + submittedVertices = [...currentVertices]; + cobwebJustSubmitted = true; + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 1: [3, 4] }, + core, + }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Move second point to a different wrong location and make sure submit button reappears + latexResults[1] = "x_{ 1 } & = 1"; + currentVertices[1] = "( 1, 1 )"; + cobwebJustSubmitted = false; + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 1: [1, 1] }, + core, + }); + await check_items(); + + // submit + submittedVertices = [...currentVertices]; + cobwebJustSubmitted = true; + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Move second point to correct location, submit + latexResults[1] = "x_{ 1 } & = 1.6667"; + currentVertices[1] = "( 1, 1.6667 )"; + submittedVertices = [...currentVertices]; + cobwebCredit = 0.2; + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 1: [1, 1.6] }, + core, + }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Add third point but don't move it, should be at graph's center, submit + currentVertices.push(`( ${graphCenterX}, ${graphCenterY} )`); + submittedVertices = [...currentVertices]; + await updateValue({ name: "/addline", core }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Move third point to correct location, submit + currentVertices[2] = "( 1.6667, 1.6667 )"; + submittedVertices = [...currentVertices]; + cobwebCredit = 0.4; + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 2: [1.6, 1.6] }, + core, + }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Add fourth point and move to wrong location, submit + latexResults.push("x_{ 2 } & = 2"); + currentVertices.push(`( 1, 2 )`); + submittedVertices = [...currentVertices]; + await updateValue({ name: "/addline", core }); + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 3: [1, 2] }, + core, + }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Move fourth point to correct location, submit + latexResults[2] = "x_{ 2 } & = 2.4074"; + currentVertices[3] = "( 1.6667, 2.4074 )"; + submittedVertices = [...currentVertices]; + cobwebCredit = 0.6; + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 3: [1.6, 2.4] }, + core, + }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Delete fourth point + let removedLatex = latexResults.pop()!; + let removedVertex = currentVertices.pop()!; + cobwebJustSubmitted = false; + await updateValue({ name: "/deleteline", core }); + await check_items(); + + // submit + submittedVertices = [...currentVertices]; + cobwebCredit = 0.4; + cobwebJustSubmitted = true; + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Add fourth point back, should remember where it had been, submit + await updateValue({ name: "/addline", core }); + latexResults.push(removedLatex); + currentVertices.push(removedVertex); + submittedVertices = [...currentVertices]; + cobwebCredit = 0.6; + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Add fifth point and move to correct location, submit + currentVertices.push(`( 2.4074, 2.4074 )`); + submittedVertices = [...currentVertices]; + cobwebCredit = 0.8; + await updateValue({ name: "/addline", core }); + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 4: [2.4, 2.4] }, + core, + }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Add sixth point and move to wrong location, submit + latexResults.push("x_{ 3 } & = 3"); + currentVertices.push(`( -1, 3 )`); + submittedVertices = [...currentVertices]; + await updateValue({ name: "/addline", core }); + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 5: [-1, 3] }, + core, + }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Move sixth point to correct location, submit + latexResults[3] = "x_{ 3 } & = 2.8829"; + currentVertices[5] = "( 2.4074, 2.8829 )"; + submittedVertices = [...currentVertices]; + cobwebCredit = 1; + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 5: [2.4, 3] }, + core, + }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Add seventh point and move to wrong location, submit + currentVertices.push(`( 3, 1 )`); + submittedVertices = [...currentVertices]; + cobwebCredit = 5 / 6; // ~0.83 + await updateValue({ name: "/addline", core }); + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 6: [3, 1] }, + core, + }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Move seventh point to correct location, submit + currentVertices[6] = "( 2.8829, 2.8829 )"; + submittedVertices = [...currentVertices]; + cobwebCredit = 1; + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 6: [3, 3] }, + core, + }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + + // Add eighth point and move to correct location, submit + latexResults[4] = "x_{ 4 } & = 2.9954"; + currentVertices[7] = "( 2.8829, 2.9954 )"; + submittedVertices = [...currentVertices]; + await updateValue({ name: "/addline", core }); + await movePolyline({ + name: "/graph1/cobweb", + pointCoords: { 7: [3, 3] }, + core, + }); + await submitAnswer({ name: "/check_cobweb", core }); + await check_items(); + }); + + it("handle bad initial point, lock to solution", async () => { + let core = await createTestCore({ + doenetML: ` + + x^2 + +

Initial point:

+ + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let vertices = stateVariables["/cobweb"].stateValues.vertices; + expect(vertices.length).eqls(100); + expect(vertices[0].map((v) => v.tree)).eqls(["_", 0]); + for (let i = 1; i < 100; i++) { + expect(vertices[i].map((v) => v.tree)).eqls([NaN, NaN]); + } + + await updateMathInputValue({ name: "/x0", latex: "0.9", core }); + stateVariables = await returnAllStateVariables(core); + vertices = stateVariables["/cobweb"].stateValues.vertices; + expect(vertices.length).eqls(100); + expect(vertices[0].map((v) => v.tree)).eqls([0.9, 0]); + expect(vertices[1].map((v) => v.tree)).eqls([0.9, 0.81]); + expect(vertices[50].map((v) => v.tree)).eqls([0, 0]); + expect(vertices[99].map((v) => v.tree)).eqls([0, 0]); + + await updateMathInputValue({ name: "/x0", latex: "(1.1,3)", core }); + stateVariables = await returnAllStateVariables(core); + vertices = stateVariables["/cobweb"].stateValues.vertices; + expect(vertices.length).eqls(100); + expect(vertices[0][0].tree).closeTo(1.1, 1e-14); + expect(vertices[0][1].tree).closeTo(3, 1e-14); + expect(vertices[1][0].tree).closeTo(1.1, 1e-14); + expect(vertices[1][1].tree).closeTo(1.21, 1e-14); + expect(vertices[50].map((v) => v.tree)).eqls([Infinity, Infinity]); + expect(vertices[99].map((v) => v.tree)).eqls([Infinity, Infinity]); + }); +}); diff --git a/packages/doenetml-worker/src/test/dynamicalsystem/equilibriumcurve.test.ts b/packages/doenetml-worker/src/test/dynamicalsystem/equilibriumcurve.test.ts new file mode 100644 index 000000000..fdbb3e75e --- /dev/null +++ b/packages/doenetml-worker/src/test/dynamicalsystem/equilibriumcurve.test.ts @@ -0,0 +1,158 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { updateBooleanInputValue } from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); +vi.mock("hyperformula"); + +describe("Equilibriumcurve Tag Tests", async () => { + it("equilibriumcurve change stable", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + +

+ $(g/A.stable{assignNames="gAs"}) + $(g/B.stable{assignNames="gBs"}) + $(g/C.stable{assignNames="gCs"}) + $(g/D.stable{assignNames="gDs"}) + +

+ + $g{name="g2"} + +

+ $(g2/A.stable{assignNames="g2As"}) + $(g2/B.stable{assignNames="g2Bs"}) + $(g2/C.stable{assignNames="g2Cs"}) + $(g2/D.stable{assignNames="g2Ds"}) + +

`, + }); + + const throughA = [ + [1, 2], + [3, 4], + [2, 6], + ]; + const throughB = [ + [3, 2], + [5, 4], + [4, 6], + ]; + const throughC = [ + [-3, 2], + [-5, 4], + [-4, 6], + ]; + const throughD = [ + [-1, 2], + [-3, 4], + [-2, 6], + ]; + let svs = await returnAllStateVariables(core); + expect(svs["/g/A"].stateValues.numericalThroughPoints).eqls(throughA); + expect(svs["/g/B"].stateValues.numericalThroughPoints).eqls(throughB); + expect(svs["/g/C"].stateValues.numericalThroughPoints).eqls(throughC); + expect(svs["/g/D"].stateValues.numericalThroughPoints).eqls(throughD); + expect(svs["/g2/A"].stateValues.numericalThroughPoints).eqls(throughA); + expect(svs["/g2/B"].stateValues.numericalThroughPoints).eqls(throughB); + expect(svs["/g2/C"].stateValues.numericalThroughPoints).eqls(throughC); + expect(svs["/g2/D"].stateValues.numericalThroughPoints).eqls(throughD); + + let As = true; + let Cs = false; + let Ds = false; + + async function check_stable() { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/gAs"].stateValues.value).eqls(As); + expect(stateVariables["/gBs"].stateValues.value).eqls(false); + expect(stateVariables["/gCs"].stateValues.value).eqls(Cs); + expect(stateVariables["/gDs"].stateValues.value).eqls(Ds); + + expect(stateVariables["/g2As"].stateValues.value).eqls(As); + expect(stateVariables["/g2Bs"].stateValues.value).eqls(false); + expect(stateVariables["/g2Cs"].stateValues.value).eqls(Cs); + expect(stateVariables["/g2Ds"].stateValues.value).eqls(Ds); + + expect(stateVariables["/g/A"].stateValues.stable).eq(As); + expect(stateVariables["/g/B"].stateValues.stable).eq(false); + expect(stateVariables["/g/C"].stateValues.stable).eq(Cs); + expect(stateVariables["/g/D"].stateValues.stable).eq(Ds); + + expect(stateVariables["/g2/A"].stateValues.stable).eq(As); + expect(stateVariables["/g2/B"].stateValues.stable).eq(false); + expect(stateVariables["/g2/C"].stateValues.stable).eq(Cs); + expect(stateVariables["/g2/D"].stateValues.stable).eq(Ds); + } + + await check_stable(); + + // switch C via boolean input + Cs = !Cs; + await updateBooleanInputValue({ name: "/b1", boolean: Cs, core }); + await check_stable(); + + // switch D via boolean input + Ds = !Ds; + await updateBooleanInputValue({ name: "/b2", boolean: Ds, core }); + await check_stable(); + + // switch A via first action + As = !As; + await core.requestAction({ + componentName: "/g/A", + actionName: "switchCurve", + args: {}, + event: null, + }); + await check_stable(); + + // switch A via second action + As = !As; + await core.requestAction({ + componentName: "/g2/A", + actionName: "switchCurve", + args: {}, + event: null, + }); + await check_stable(); + + // cannot switch B via action + await core.requestAction({ + componentName: "/g/B", + actionName: "switchCurve", + args: {}, + event: null, + }); + await check_stable(); + + // cannot switch C via second action + await core.requestAction({ + componentName: "/g2/C", + actionName: "switchCurve", + args: {}, + event: null, + }); + await check_stable(); + + // switch D via second action + Ds = !Ds; + await core.requestAction({ + componentName: "/g2/D", + actionName: "switchCurve", + args: {}, + event: null, + }); + }); +}); diff --git a/packages/doenetml-worker/src/test/dynamicalsystem/equilibriumline.test.ts b/packages/doenetml-worker/src/test/dynamicalsystem/equilibriumline.test.ts new file mode 100644 index 000000000..c88061bb1 --- /dev/null +++ b/packages/doenetml-worker/src/test/dynamicalsystem/equilibriumline.test.ts @@ -0,0 +1,140 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { updateBooleanInputValue } from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); +vi.mock("hyperformula"); + +describe("Equilibriumline Tag Tests", async () => { + it("equilibriumline change stable", async () => { + let core = await createTestCore({ + doenetML: ` + + y=4 + y=7 + y=-9 + y=-3 + + + + + +

+ $(g/A.stable{assignNames="gAs"}) + $(g/B.stable{assignNames="gBs"}) + $(g/C.stable{assignNames="gCs"}) + $(g/D.stable{assignNames="gDs"}) + +

+ + $g{name="g2"} + +

+ $(g2/A.stable{assignNames="g2As"}) + $(g2/B.stable{assignNames="g2Bs"}) + $(g2/C.stable{assignNames="g2Cs"}) + $(g2/D.stable{assignNames="g2Ds"}) + +

+

`, + }); + + const equationA = ["=", "y", 4]; + const equationB = ["=", "y", 7]; + const equationC = ["=", "y", -9]; + const equationD = ["=", "y", -3]; + let svs = await returnAllStateVariables(core); + expect(svs["/g/A"].stateValues.equation.tree).eqls(equationA); + expect(svs["/g/B"].stateValues.equation.tree).eqls(equationB); + expect(svs["/g/C"].stateValues.equation.tree).eqls(equationC); + expect(svs["/g/D"].stateValues.equation.tree).eqls(equationD); + expect(svs["/g2/A"].stateValues.equation.tree).eqls(equationA); + expect(svs["/g2/B"].stateValues.equation.tree).eqls(equationB); + expect(svs["/g2/C"].stateValues.equation.tree).eqls(equationC); + expect(svs["/g2/D"].stateValues.equation.tree).eqls(equationD); + + let As = true; + let Cs = false; + let Ds = false; + + async function check_stable() { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/gAs"].stateValues.value).eqls(As); + expect(stateVariables["/gBs"].stateValues.value).eqls(false); + expect(stateVariables["/gCs"].stateValues.value).eqls(Cs); + expect(stateVariables["/gDs"].stateValues.value).eqls(Ds); + expect(stateVariables["/g2As"].stateValues.value).eqls(As); + expect(stateVariables["/g2Bs"].stateValues.value).eqls(false); + expect(stateVariables["/g2Cs"].stateValues.value).eqls(Cs); + expect(stateVariables["/g2Ds"].stateValues.value).eqls(Ds); + expect(stateVariables["/g/A"].stateValues.stable).eq(As); + expect(stateVariables["/g/B"].stateValues.stable).eq(false); + expect(stateVariables["/g/C"].stateValues.stable).eq(Cs); + expect(stateVariables["/g/D"].stateValues.stable).eq(Ds); + expect(stateVariables["/g2/A"].stateValues.stable).eq(As); + expect(stateVariables["/g2/B"].stateValues.stable).eq(false); + expect(stateVariables["/g2/C"].stateValues.stable).eq(Cs); + expect(stateVariables["/g2/D"].stateValues.stable).eq(Ds); + } + + await check_stable(); + + // switch C via boolean input + Cs = !Cs; + await updateBooleanInputValue({ name: "/b1", boolean: Cs, core }); + await check_stable(); + + // switch D via boolean input + Ds = !Ds; + await updateBooleanInputValue({ name: "/b2", boolean: Ds, core }); + await check_stable(); + + // switch A via first action + As = !As; + await core.requestAction({ + componentName: "/g/A", + actionName: "switchLine", + args: {}, + event: null, + }); + await check_stable(); + + // switch A via second action + As = !As; + await core.requestAction({ + componentName: "/g2/A", + actionName: "switchLine", + args: {}, + event: null, + }); + await check_stable(); + + // cannot switch B via action + await core.requestAction({ + componentName: "/g/B", + actionName: "switchLine", + args: {}, + event: null, + }); + await check_stable(); + + // cannot switch C via second action + await core.requestAction({ + componentName: "/g2/C", + actionName: "switchLine", + args: {}, + event: null, + }); + await check_stable(); + + // switch D via second action + Ds = !Ds; + await core.requestAction({ + componentName: "/g2/D", + actionName: "switchLine", + args: {}, + event: null, + }); + }); +}); diff --git a/packages/doenetml-worker/src/test/dynamicalsystem/equilibriumpoint.test.ts b/packages/doenetml-worker/src/test/dynamicalsystem/equilibriumpoint.test.ts new file mode 100644 index 000000000..90c23bef3 --- /dev/null +++ b/packages/doenetml-worker/src/test/dynamicalsystem/equilibriumpoint.test.ts @@ -0,0 +1,140 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { updateBooleanInputValue } from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); +vi.mock("hyperformula"); + +describe("Equilibriumpoint Tag Tests", async () => { + it("equilibriumpoint change stable", async () => { + let core = await createTestCore({ + doenetML: ` + + (4,0) + (7,0) + (-9,0) + (-3,0) + + + + + +

+ $(g/A.stable{assignNames="gAs"}) + $(g/B.stable{assignNames="gBs"}) + $(g/C.stable{assignNames="gCs"}) + $(g/D.stable{assignNames="gDs"}) + +

+ + $g{name="g2"} + +

+ $(g2/A.stable{assignNames="g2As"}) + $(g2/B.stable{assignNames="g2Bs"}) + $(g2/C.stable{assignNames="g2Cs"}) + $(g2/D.stable{assignNames="g2Ds"}) + +

+ `, + }); + + const pointA = [4, 0]; + const pointB = [7, 0]; + const pointC = [-9, 0]; + const pointD = [-3, 0]; + let svs = await returnAllStateVariables(core); + expect(svs["/g/A"].stateValues.xs.map((v) => v.tree)).eqls(pointA); + expect(svs["/g/B"].stateValues.xs.map((v) => v.tree)).eqls(pointB); + expect(svs["/g/C"].stateValues.xs.map((v) => v.tree)).eqls(pointC); + expect(svs["/g/D"].stateValues.xs.map((v) => v.tree)).eqls(pointD); + expect(svs["/g2/A"].stateValues.xs.map((v) => v.tree)).eqls(pointA); + expect(svs["/g2/B"].stateValues.xs.map((v) => v.tree)).eqls(pointB); + expect(svs["/g2/C"].stateValues.xs.map((v) => v.tree)).eqls(pointC); + expect(svs["/g2/D"].stateValues.xs.map((v) => v.tree)).eqls(pointD); + + let As = true; + let Cs = false; + let Ds = false; + + async function check_stable() { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/gAs"].stateValues.value).eqls(As); + expect(stateVariables["/gBs"].stateValues.value).eqls(false); + expect(stateVariables["/gCs"].stateValues.value).eqls(Cs); + expect(stateVariables["/gDs"].stateValues.value).eqls(Ds); + expect(stateVariables["/g2As"].stateValues.value).eqls(As); + expect(stateVariables["/g2Bs"].stateValues.value).eqls(false); + expect(stateVariables["/g2Cs"].stateValues.value).eqls(Cs); + expect(stateVariables["/g2Ds"].stateValues.value).eqls(Ds); + expect(stateVariables["/g/A"].stateValues.stable).eq(As); + expect(stateVariables["/g/B"].stateValues.stable).eq(false); + expect(stateVariables["/g/C"].stateValues.stable).eq(Cs); + expect(stateVariables["/g/D"].stateValues.stable).eq(Ds); + expect(stateVariables["/g2/A"].stateValues.stable).eq(As); + expect(stateVariables["/g2/B"].stateValues.stable).eq(false); + expect(stateVariables["/g2/C"].stateValues.stable).eq(Cs); + expect(stateVariables["/g2/D"].stateValues.stable).eq(Ds); + } + + await check_stable(); + + // switch C via boolean input + Cs = !Cs; + await updateBooleanInputValue({ name: "/b1", boolean: Cs, core }); + await check_stable(); + + // switch D via boolean input + Ds = !Ds; + await updateBooleanInputValue({ name: "/b2", boolean: Ds, core }); + await check_stable(); + + // switch A via first action + As = !As; + await core.requestAction({ + componentName: "/g/A", + actionName: "switchPoint", + args: {}, + event: null, + }); + await check_stable(); + + // switch A via second action + As = !As; + await core.requestAction({ + componentName: "/g2/A", + actionName: "switchPoint", + args: {}, + event: null, + }); + await check_stable(); + + // cannot switch B via action + await core.requestAction({ + componentName: "/g/B", + actionName: "switchPoint", + args: {}, + event: null, + }); + await check_stable(); + + // cannot switch C via second action + await core.requestAction({ + componentName: "/g2/C", + actionName: "switchPoint", + args: {}, + event: null, + }); + await check_stable(); + + // switch D via second action + Ds = !Ds; + await core.requestAction({ + componentName: "/g2/D", + actionName: "switchPoint", + args: {}, + event: null, + }); + }); +}); diff --git a/packages/doenetml-worker/src/test/dynamicalsystem/odesystem.test.ts b/packages/doenetml-worker/src/test/dynamicalsystem/odesystem.test.ts new file mode 100644 index 000000000..229a7070b --- /dev/null +++ b/packages/doenetml-worker/src/test/dynamicalsystem/odesystem.test.ts @@ -0,0 +1,808 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { createFunctionFromDefinition } from "@doenet/utils"; +import { + movePoint, + updateBooleanInputValue, + updateMathInputValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); +vi.mock("hyperformula"); + +describe("ODEsystem Tag Tests", async () => { + it("1D linear system", async () => { + let core = await createTestCore({ + doenetML: ` +

a =

+

initial condition =

+

tol =

+ + + $a x + + + + $ode.numericalSolution{assignNames="f"} + + + +

+ + + + +

+ +0 +$tol.value{assignNames="tol2"} + `, + }); + + let ic = 1; + let a = 1; + let tol = 1e-6; + let expectedF = (x) => ic * Math.exp(a * x); + + async function check_items() { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/tol2"].stateValues.value.tree).eqls(tol); + expect(stateVariables["/ode"].stateValues.latex).eqls( + `\\frac{dx}{dt} &= ${a === 1 ? "" : a + " "}x\\notag\\\\x(0) &= ${ic}\\notag`, + ); + let solutionF = createFunctionFromDefinition( + stateVariables["/ode"].stateValues + .numericalSolutionFDefinitions[0], + ); + + let solutionsFromCore = stateVariables["/map1"] + .replacements!.map( + (child) => + stateVariables[child.componentName].replacements![0], + ) + .map( + (grandChild) => + stateVariables[grandChild.componentName].stateValues + .value, + ) + .map((v) => v.tree); + + for (let x = 0; x <= 5; x += 0.5) { + expect(solutionF(x)).closeTo( + expectedF(x), + tol * Math.max(1, Math.abs(expectedF(x))), + ); + expect(solutionsFromCore[2 * x]).eq(solutionF(x)); + } + } + + await check_items(); + + // Change initial condition + ic = 3; + expectedF = (x) => ic * Math.exp(a * x); + await updateMathInputValue({ name: "/ic", latex: "3", core }); + await check_items(); + + // Change parameter + a = -2; + expectedF = (x) => ic * Math.exp(a * x); + await updateMathInputValue({ name: "/a", latex: "-2", core }); + await check_items(); + + // Change ic with point + ic = -5; + expectedF = (x) => ic * Math.exp(a * x); + await movePoint({ name: "/point1", x: 0, y: ic, core }); + await check_items(); + + // Change tolerance + tol = 1e-10; + await updateMathInputValue({ name: "/tol", latex: "1E-10", core }); + + // Change parameter again + a = 0.5; + expectedF = (x) => ic * Math.exp(a * x); + await updateMathInputValue({ name: "/a", latex: "0.5", core }); + await check_items(); + + // Change initial condition to zero + ic = 0; + expectedF = (x) => 0; + await updateMathInputValue({ name: "/ic", latex: "0", core }); + await check_items(); + }); + + it("effect of max iterations, chunksize", async () => { + let core = await createTestCore({ + doenetML: ` +

tol =

+

T =

+

maxIter =

+

chunkSize =

+ + x + + +

f($T) = $$(ode.numericalSolution)($T)

+ `, + }); + + let tol = 1e-6; + let T = 10; + let maxIter = 1000; + let chunkSize = 10; + + async function check_items({ + solverSuccess, + }: { + solverSuccess: boolean; + }) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/T"].stateValues.value.tree).eqls(T); + expect(stateVariables["/tol"].stateValues.value.tree).eqls(tol); + expect(stateVariables["/maxIter"].stateValues.value.tree).eqls( + maxIter, + ); + expect(stateVariables["/chunkSize"].stateValues.value.tree).eqls( + chunkSize, + ); + + let solutionF = createFunctionFromDefinition( + stateVariables["/ode"].stateValues + .numericalSolutionFDefinitions[0], + ); + let f_T_copied = Number( + stateVariables["/m1"].stateValues.text.split("=")[1], + ); + + if (!solverSuccess) { + // Ensure numerical solution at t=T is NaN + expect(solutionF(T)).eqls(NaN); + expect(f_T_copied).eqls(NaN); + } else { + // Ensure numerical solution for range [0,T] follows expected solution + const expectedF = (x) => Math.exp(x); + for (let x = 0; x <= T; x += 1) { + expect(solutionF(x)).closeTo( + expectedF(x), + tol * Math.max(1, Math.abs(expectedF(x))), + ); + } + expect(f_T_copied).closeTo( + expectedF(T), + tol * Math.max(1, Math.abs(expectedF(T))), + ); + } + } + + await check_items({ solverSuccess: true }); + + // Solver algorithm runs past max iterations before it can + // solve f(20) within required threshold + T = 20; + await updateMathInputValue({ name: "/T", latex: `${T}`, core }); + await check_items({ solverSuccess: false }); + + // increase max iterations, now f(20) works + maxIter = 2000; + await updateMathInputValue({ + name: "/maxIter", + latex: `${maxIter}`, + core, + }); + await check_items({ solverSuccess: true }); + + // Can't make it if decrease tolerance + tol = 1e-8; + await updateMathInputValue({ name: "/tol", latex: `1E-8`, core }); + await check_items({ solverSuccess: false }); + + // increase max iterations further + maxIter = 5000; + await updateMathInputValue({ + name: "/maxIter", + latex: `${maxIter}`, + core, + }); + await check_items({ solverSuccess: true }); + + // decrease max iterations back down to original, fails + maxIter = 1000; + await updateMathInputValue({ + name: "/maxIter", + latex: `${maxIter}`, + core, + }); + await check_items({ solverSuccess: false }); + + // decrease chunksize + chunkSize = 1; + await updateMathInputValue({ + name: "/chunkSize", + latex: `${chunkSize}`, + core, + }); + await check_items({ solverSuccess: true }); + }); + + it("change variables 1D", async () => { + let core = await createTestCore({ + doenetML: ` +

independent variable =

+

dependent variable =

+ + + $dVar + + + + $ode.numericalSolution{assignNames="f"} + + +

+ + + + +

+ `, + }); + + let tol = 1e-6; + let iVar = "t"; + let dVar = "x"; + let expectedF = (x) => Math.exp(x); + + async function check_items() { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ode"].stateValues.latex).eqls( + `\\frac{d${dVar}}{d${iVar}} &= ${dVar}\\notag\\\\${dVar}(0) &= 1\\notag`, + ); + let solutionF = createFunctionFromDefinition( + stateVariables["/ode"].stateValues + .numericalSolutionFDefinitions[0], + ); + let solutionsFromCore = stateVariables["/map1"].replacements!.map( + (x) => + stateVariables[ + stateVariables[x.componentName].replacements![0] + .componentName + ].stateValues.value.tree, + ); + + for (let t = 0; t <= 5; t += 1) { + if (Number.isNaN(expectedF(t))) { + expect(solutionF(t)).toBeNaN(); + expect(solutionsFromCore[t]).toBeNaN(); + } else { + expect(solutionF(t)).closeTo( + expectedF(t), + tol * Math.max(1, Math.abs(expectedF(t))), + ); + expect(solutionsFromCore[t]).eq(solutionF(t)); + } + } + } + + await check_items(); + + // change independent variable + iVar = "s"; + await updateMathInputValue({ name: "/iVar", latex: iVar, core }); + await check_items(); + + // erase independent variable + iVar = "_"; + expectedF = (x) => (x === 0 ? 1 : NaN); + await updateMathInputValue({ name: "/iVar", latex: "", core }); + await check_items(); + + // restore independent variable + iVar = "u"; + expectedF = (x) => Math.exp(x); + await updateMathInputValue({ name: "/iVar", latex: iVar, core }); + await check_items(); + + // invalid independent variable + iVar = "1"; + expectedF = (x) => (x === 0 ? 1 : NaN); + await updateMathInputValue({ name: "/iVar", latex: iVar, core }); + await check_items(); + + // restore independent variable + iVar = "v"; + expectedF = (x) => Math.exp(x); + await updateMathInputValue({ name: "/iVar", latex: iVar, core }); + await check_items(); + + // change dependent variable + dVar = "z"; + await updateMathInputValue({ name: "/dVar", latex: dVar, core }); + await check_items(); + + // duplicate variable + dVar = iVar; + expectedF = (x) => (x === 0 ? 1 : NaN); + await updateMathInputValue({ name: "/dVar", latex: dVar, core }); + await check_items(); + + // different dependent variable + dVar = "v_{1}"; + expectedF = (x) => Math.exp(x); + await updateMathInputValue({ name: "/dVar", latex: "v_1", core }); + await check_items(); + + // invalid dependent variable + dVar = "a b"; + expectedF = (x) => (x === 0 ? 1 : NaN); + await updateMathInputValue({ name: "/dVar", latex: "ab", core }); + await check_items(); + + // restore dependent variable + dVar = "a"; + expectedF = (x) => Math.exp(x); + await updateMathInputValue({ name: "/dVar", latex: dVar, core }); + await check_items(); + }); + + it("display digits", async () => { + let core = await createTestCore({ + doenetML: ` +

display digits =

+ + 0.123456789123456789x + +`, + }); + + let a = "0.1234567891"; + let ic = "9.87654322"; + + async function check_items({ a, ic }: { a: string; ic: string }) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ode"].stateValues.latex).eqls( + `\\frac{dx}{dt} &= ${a} x\\notag\\\\x(0) &= ${ic}\\notag`, + ); + } + await check_items({ a, ic }); + + // 2 display digits + a = "0.12"; + ic = "9.9"; + await updateMathInputValue({ name: "/digits", latex: "2", core }); + await check_items({ a, ic }); + + // 14 display digits + a = "0.12345678912346"; + ic = "9.8765432198765"; + await updateMathInputValue({ name: "/digits", latex: "14", core }); + await check_items({ a, ic }); + }); + + it("initial independent variable value", async () => { + let core = await createTestCore({ + doenetML: ` +

initial t =

+

final t =

+ + + x + + +

We started with + x($ode.initialIndependentVariableValue) = 1.

+ +

We end with + x($tf) = $$(ode.numericalSolution)($tf)

+`, + }); + + let t0 = 0; + let tf = 10; + + async function check_items() { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ode"].stateValues.latex).eqls( + `\\frac{dx}{dt} &= x\\notag\\\\x(${t0}) &= 1\\notag`, + ); + + expect( + stateVariables["/ode"].stateValues + .initialIndependentVariableValue.tree, + ).eqls(t0); + + let startPieces = stateVariables["/m1"].stateValues.latex + .split("=") + .map((v) => v.trim()); + expect(startPieces.length).eqls(2); + expect(startPieces[0]).eqls(`x( ${t0} )`); + + let finalPieces = stateVariables["/m2"].stateValues.latex + .split("=") + .map((v) => v.trim()); + expect(finalPieces.length).eqls(2); + expect(finalPieces[0]).eqls(`x( ${tf} )`); + expect(Number(finalPieces[1])).closeTo( + Math.exp(tf - t0), + 1e-6 * Math.exp(tf - t0), + ); + } + + await check_items(); + + // Change initial time + t0 = -5; + await updateMathInputValue({ name: "/t0", latex: `${t0}`, core }); + await check_items(); + + // Change initial and final time + t0 = 11; + tf = 12; + await updateMathInputValue({ name: "/t0", latex: `${t0}`, core }); + await updateMathInputValue({ name: "/tf", latex: `${tf}`, core }); + await check_items(); + }); + + it("display initial conditions", async () => { + let core = await createTestCore({ + doenetML: ` +

display initial conditions:

+ + x + +`, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ode"].stateValues.latex).eqls( + `\\frac{dx}{dt} &= x\\notag\\\\x(0) &= 1\\notag`, + ); + + // don't display initial conditions + await updateBooleanInputValue({ + name: "/showic", + boolean: false, + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ode"].stateValues.latex).eqls( + `\\frac{dx}{dt} &= x\\notag`, + ); + + // display initial conditions again + await updateBooleanInputValue({ name: "/showic", boolean: true, core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ode"].stateValues.latex).eqls( + `\\frac{dx}{dt} &= x\\notag\\\\x(0) &= 1\\notag`, + ); + }); + + it("2D linear system", async () => { + let core = await createTestCore({ + doenetML: ` +

initial condition 1 =

+

initial condition 2 =

+ + -0.2y + 0.1x + 0.3y + + + + + $ode.numericalsolutions{assignNames="f1 f2"} + + + + +

+ + + + +

+`, + }); + + let tol = 1e-6; + let ic1 = 1; + let ic2 = 3; + let expectedFx = (t) => 8 * Math.exp(0.1 * t) - 7 * Math.exp(0.2 * t); + let expectedFy = (t) => -4 * Math.exp(0.1 * t) + 7 * Math.exp(0.2 * t); + + async function check_items() { + let stateVariables = await returnAllStateVariables(core); + let ode = stateVariables["/ode"]; + expect(ode.stateValues.latex).eqls( + `\\frac{dx}{dt} &= -0.2 y\\notag\\\\\\frac{dy}{dt} &= 0.1 x + 0.3 y\\notag\\\\x(0) &= ${ic1}\\notag\\\\y(0) &= ${ic2}\\notag`, + ); + + let solutionFx = createFunctionFromDefinition( + ode.stateValues.numericalSolutionFDefinitions[0], + ); + let solutionFy = createFunctionFromDefinition( + ode.stateValues.numericalSolutionFDefinitions[1], + ); + let solutionFx2 = createFunctionFromDefinition( + stateVariables["/f1"].stateValues.fDefinitions[0], + ); + let solutionFy2 = createFunctionFromDefinition( + stateVariables["/f2"].stateValues.fDefinitions[0], + ); + let solutionsFromCoreX = stateVariables["/map1"] + .replacements!.map( + (child) => + stateVariables[child.componentName].replacements![0], + ) + .map( + (grandChild) => + stateVariables[grandChild.componentName].stateValues + .value, + ) + .map((v) => v.tree); + let solutionsFromCoreY = stateVariables["/map1"] + .replacements!.map( + (child) => + stateVariables[child.componentName].replacements![1], + ) + .map( + (grandChild) => + stateVariables[grandChild.componentName].stateValues + .value, + ) + .map((v) => v.tree); + + for (let t = 0; t <= 10; t += 1) { + expect(solutionFx(t)).closeTo( + expectedFx(t), + tol * Math.max(1, Math.abs(expectedFx(t))), + ); + expect(solutionFy(t)).closeTo( + expectedFy(t), + tol * Math.max(1, Math.abs(expectedFy(t))), + ); + expect(solutionFx2(t)).eq(solutionFx(t)); + expect(solutionFy2(t)).eq(solutionFy(t)); + expect(solutionsFromCoreX[t]).eq(solutionFx(t)); + expect(solutionsFromCoreY[t]).eq(solutionFy(t)); + } + } + + await check_items(); + + // Change initial condition + ic1 = 3; + ic2 = -1; + expectedFx = (t) => 4 * Math.exp(0.1 * t) - 1 * Math.exp(0.2 * t); + expectedFy = (t) => -2 * Math.exp(0.1 * t) + 1 * Math.exp(0.2 * t); + await updateMathInputValue({ name: "/ic1", latex: `${ic1}`, core }); + await updateMathInputValue({ name: "/ic2", latex: `${ic2}`, core }); + await check_items(); + + // Change ic with point + ic1 = -5; + ic2 = 2; + expectedFx = (t) => -6 * Math.exp(0.1 * t) + 1 * Math.exp(0.2 * t); + expectedFy = (t) => 3 * Math.exp(0.1 * t) - 1 * Math.exp(0.2 * t); + await movePoint({ name: "/point1", x: ic1, y: ic2, core }); + await check_items(); + + // Change initial condition to zero + ic1 = 0; + ic2 = 0; + expectedFx = (t) => 0; + expectedFy = (t) => 0; + await updateMathInputValue({ name: "/ic1", latex: `${ic1}`, core }); + await updateMathInputValue({ name: "/ic2", latex: `${ic2}`, core }); + await check_items(); + }); + + it("higher dimensional ode", async () => { + const rightHandSides = ["q", "r", "s", "u", "v", "w"]; + const initialConditions = ["a", "b", "c", "d", "e", "f"]; + + async function check_ode_latex({ + doenetML, + varNames, + }: { + doenetML: string; + varNames: string[]; + }) { + let odeLatex = ""; + for (let i = 0; i < varNames.length; i++) { + odeLatex += `\\frac{d${varNames[i]}}{dt} &= ${rightHandSides[i]}\\notag\\\\`; + } + for (let i = 0; i < varNames.length; i++) { + odeLatex += `${varNames[i]}(0) &= ${initialConditions[i]}\\notag\\\\`; + } + odeLatex = odeLatex.substring(0, odeLatex.length - 2); // remove ending "\\" + + let core = await createTestCore({ doenetML }); + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ode"].stateValues.latex).eqls(odeLatex); + } + + // No variables specified + let doenetML = ` + +q +r +s +u +v +w + + `; + let varNames = ["x_{1}", "x_{2}", "x_{3}", "x_{4}", "x_{5}", "x_{6}"]; + await check_ode_latex({ doenetML, varNames }); + + // all variables specified + doenetML = ` + +q +r +s +u +v +w + + `; + varNames = ["j", "k", "l", "m", "n", "p"]; + await check_ode_latex({ doenetML, varNames }); + + // some variables specified + doenetML = ` + +q +r +s +u +v +w + + `; + varNames = ["j", "k", "l", "x_{4}", "x_{5}", "x_{6}"]; + await check_ode_latex({ doenetML, varNames }); + }); + + it("copy righthandside, initial conditions", async () => { + let core = await createTestCore({ + doenetML: ` + + a*x*y+z + x/y + + +

RHS1: $ode.rhs1{name="rhs1a"}

+

RHS2: $ode.rhs2{name="rhs2a"}

+

RHS1: $ode.rhs{name="rhs1b"}

+

Both RHSs: $ode.rhss{name="rhssa"}

+ +

RHS1: $ode.righthandside1{name="rhs1c"}

+

RHS2: $ode.righthandside2{name="rhs2b"}

+

RHS1: $ode.righthandside{name="rhs1d"}

+

Both RHSs: $ode.righthandsides{name="rhssb"}

+ +

IC1: $ode.initialcondition1{name="ic1a"}

+

IC2: $ode.initialcondition2{name="ic2a"}

+

IC1: $ode.initialcondition{name="ic1b"}

+

Both ICs: $ode.initialconditions{name="icsa"}

+ +

Swap right hand sides and keep initial conditions

+ + + $ode.rhs2 + $ode.rhs1 + +`, + }); + + let stateVariables = await returnAllStateVariables(core); + let rhs1tree = ["+", ["*", "a", "x", "y"], "z"]; + let rhs2tree = ["/", "x", "y"]; + + function expectReplacement( + origName: string, + repNum: number, + desiredValue: any, + ) { + expect( + stateVariables[ + stateVariables[origName].replacements![repNum].componentName + ].stateValues.value.tree, + ).eqls(desiredValue); + } + + expectReplacement("/rhs1a", 0, rhs1tree); + expectReplacement("/rhs2a", 0, rhs2tree); + expectReplacement("/rhs1b", 0, rhs1tree); + expectReplacement("/rhssa", 0, rhs1tree); + expectReplacement("/rhssa", 1, rhs2tree); + + expectReplacement("/rhs1c", 0, rhs1tree); + expectReplacement("/rhs2b", 0, rhs2tree); + expectReplacement("/rhs1d", 0, rhs1tree); + expectReplacement("/rhssb", 0, rhs1tree); + expectReplacement("/rhssb", 1, rhs2tree); + + expectReplacement("/ic1a", 0, "c"); + expectReplacement("/ic2a", 0, 3); + expectReplacement("/ic1b", 0, "c"); + expectReplacement("/icsa", 0, "c"); + expectReplacement("/icsa", 1, 3); + + let swapLatex = ""; + swapLatex += "\\frac{dx}{dt} &= \\frac{x}{y}\\notag\\\\"; + swapLatex += "\\frac{dy}{dt} &= a x y + z\\notag\\\\"; + swapLatex += "x(0) &= c\\notag\\\\"; + swapLatex += "y(0) &= 3\\notag"; + expect(stateVariables["/odeswap"].stateValues.latex).eqls(swapLatex); + }); + + it("warnings", async () => { + let core = await createTestCore({ + doenetML: ` +a + + 5y + + + + 5y + + + + 5y + + + + 5x + 3x + +`, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(4); + + expect(errorWarnings.warnings[0].message).contain( + `Invalid value of a variable: sin(x)`, + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(7); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(47); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(7); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(52); + + expect(errorWarnings.warnings[1].message).contain( + `Variables of must be different than independent variable`, + ); + expect(errorWarnings.warnings[1].level).eq(1); + expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(3); + expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(1); + expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(5); + expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(12); + + expect(errorWarnings.warnings[2].message).contain( + `Invalid value of a variable: sin(y)`, + ); + expect(errorWarnings.warnings[2].level).eq(1); + expect(errorWarnings.warnings[2].doenetMLrange.lineBegin).eq(11); + expect(errorWarnings.warnings[2].doenetMLrange.charBegin).eq(23); + expect(errorWarnings.warnings[2].doenetMLrange.lineEnd).eq(11); + expect(errorWarnings.warnings[2].doenetMLrange.charEnd).eq(28); + + expect(errorWarnings.warnings[3].message).contain( + `Can't define ODE RHS functions with duplicate dependent variable names`, + ); + expect(errorWarnings.warnings[3].level).eq(1); + expect(errorWarnings.warnings[3].doenetMLrange.lineBegin).eq(15); + expect(errorWarnings.warnings[3].doenetMLrange.charBegin).eq(1); + expect(errorWarnings.warnings[3].doenetMLrange.lineEnd).eq(18); + expect(errorWarnings.warnings[3].doenetMLrange.charEnd).eq(12); + }); +}); diff --git a/packages/test-cypress/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js b/packages/test-cypress/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js index e7d4c3bf6..71e057352 100644 --- a/packages/test-cypress/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js +++ b/packages/test-cypress/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js @@ -6,1851 +6,6 @@ describe("CobwebPolyline Tag Tests", function () { cy.visit("/"); }); - it("logistic system", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 1/3*x*(3-x)+x - 1 - - - - - - - - -

Initial condition is x_0 = 1: - - - $P1.coords = (1,0) - - -

- - - - - - - - - - x_n - x_{n+1} - - - - - - Result of cobweb sketch - - - - - - $(graph1/cobweb.iterateValues) - - - - - - -

Cobweb at least three iterations

-

- true - - $(graph1/cobweb.vertices) - - -

- -

Submitted responses are the vertices of the polyline:

- - Current responses are the vertices of the polyline: - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let xCenter = (-2 + 5) / 2, - yCenter = (-2.2 + 4.5) / 2; - - cy.get(cesc("#\\/_p1")).should("contain.text", "Initial condition is"); - - cy.log("Click both submit buttons"); - cy.get(cesc("#\\/check_initial_submit")).click(); - cy.get(cesc("#\\/check_initial_incorrect")).should("be.visible"); - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_incorrect")).should("be.visible"); - - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=−1.5"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(1).should("not.exist"); - - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1.5,0)"); - }); - cy.get(cesc("#\\/psr")).find(".mjx-mrow").eq(2).should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1.5,0)"); - }); - cy.get(cesc("#\\/cr2")).should("not.exist"); - - cy.log("Move first point"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 0: [1, 0] }, - sourceDetails: { vertex: 0 }, - }, - }); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should( - "contain.text", - "(1,0)", - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_initial_submit")).click(); - cy.get(cesc("#\\/check_initial_correct")).should("be.visible"); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(1).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1.5,0)"); - }); - cy.get(cesc("#\\/psr")).find(".mjx-mrow").eq(2).should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2")).should("not.exist"); - - cy.log("Add second point"); - - cy.get(cesc("#\\/addline_button")).click(); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow").should( - "contain.text", - `(${xCenter},${yCenter})`, - ); - - cy.log("Move second point to wrong location"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 1: [3, 4] }, - sourceDetails: { vertex: 1 }, - }, - }); - }); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow").should( - "contain.text", - "(3,4)", - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=4"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(2).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc("#\\/psr")).find(".mjx-mrow").eq(4).should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc("#\\/cr3")).should("not.exist"); - - cy.log("Move second point to second wrong location"); - - // Note: move to second wrong point to make sure submit button reappears - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 1: [1, 1] }, - sourceDetails: { vertex: 1 }, - }, - }); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow").should( - "contain.text", - "(1,1)", - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(2).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1)"); - }); - cy.get(cesc("#\\/psr")).find(".mjx-mrow").eq(4).should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1)"); - }); - cy.get(cesc("#\\/cr3")).should("not.exist"); - - cy.log("Move second point to correct location"); - - cy.window().then(async () => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 1: [1, 1.6] }, - sourceDetails: { vertex: 1 }, - }, - }); - }); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow").should( - "contain.text", - "(1,1.6667)", - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("20% correct"); - }); - - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(2).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")).find(".mjx-mrow").eq(4).should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3")).should("not.exist"); - - cy.log("Add third point"); - - // don't move to check that it is at center of graph - cy.get(cesc("#\\/addline_button")).click(); - - cy.get(cesc("#\\/cr3") + " .mjx-mrow").should( - "contain.text", - `(${xCenter},${yCenter})`, - ); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_partial")).should( - "contain.text", - "20%", - ); - cy.get(cesc("#\\/check_cobweb_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("20% correct"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(2).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(${xCenter},${yCenter})`); - }); - cy.get(cesc("#\\/psr")).find(".mjx-mrow").eq(6).should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(${xCenter},${yCenter})`); - }); - cy.get(cesc("#\\/cr4")).should("not.exist"); - - cy.log("Move third point to correct location"); - - cy.window().then(async () => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 2: [1.6, 1.6] }, - sourceDetails: { vertex: 2 }, - }, - }); - }); - - cy.get(cesc("#\\/cr3") + " .mjx-mrow").should( - "contain.text", - `(1.6667,1.6667)`, - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_partial")).should( - "contain.text", - "40%", - ); - cy.get(cesc("#\\/check_cobweb_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("40% correct"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(2).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,1.6667)"); - }); - cy.get(cesc("#\\/psr")).find(".mjx-mrow").eq(6).should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,1.6667)`); - }); - cy.get(cesc("#\\/cr4")).should("not.exist"); - - cy.log("Add fourth point and move to wrong location"); - - cy.get(cesc("#\\/addline_button")).click(); - - cy.get(cesc("#\\/cr4") + " .mjx-mrow").should( - "contain.text", - `(${xCenter},${yCenter})`, - ); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 3: [1, 2] }, - sourceDetails: { vertex: 3 }, - }, - }); - }); - - cy.get(cesc("#\\/cr4") + " .mjx-mrow").should( - "contain.text", - `(1,2)`, - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_partial")).should( - "contain.text", - "40%", - ); - - cy.get(cesc("#\\/check_cobweb_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("40% correct"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2=2"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(3).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(6) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - cy.get(cesc("#\\/psr")).find(".mjx-mrow").eq(8).should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,1.6667)`); - }); - cy.get(cesc("#\\/cr4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1,2)`); - }); - cy.get(cesc("#\\/cr5")).should("not.exist"); - - cy.log("Move fourth point to correct location"); - - cy.window().then(async () => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 3: [1.6, 2.4] }, - sourceDetails: { vertex: 3 }, - }, - }); - }); - - cy.get(cesc("#\\/cr4") + " .mjx-mrow").should( - "contain.text", - `(1.6667,2.4074)`, - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_partial")).should( - "contain.text", - "60%", - ); - cy.get(cesc("#\\/check_cobweb_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("60% correct"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2=2.4074"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(3).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(6) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,2.4074)"); - }); - cy.get(cesc("#\\/psr")).find(".mjx-mrow").eq(8).should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,1.6667)`); - }); - cy.get(cesc("#\\/cr4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,2.4074)`); - }); - cy.get(cesc("#\\/cr5")).should("not.exist"); - - cy.log("Delete fourth point"); - cy.get(cesc("#\\/deleteline_button")).click(); - - cy.get(cesc("#\\/cr4")).should("not.exist"); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_partial")).should( - "contain.text", - "40%", - ); - cy.get(cesc("#\\/check_cobweb_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("40% correct"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(2).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,1.6667)"); - }); - cy.get(cesc("#\\/psr")).find(".mjx-mrow").eq(6).should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,1.6667)`); - }); - cy.get(cesc("#\\/cr4")).should("not.exist"); - - cy.log("Add fourth point back"); - cy.get(cesc("#\\/addline_button")).click(); - - cy.get(cesc("#\\/cr4") + " .mjx-mrow").should( - "contain.text", - `(1.6667,2.4074)`, - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_partial")).should( - "contain.text", - "60%", - ); - cy.get(cesc("#\\/check_cobweb_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("60% correct"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2=2.4074"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(3).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(6) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,2.4074)"); - }); - cy.get(cesc("#\\/psr")).find(".mjx-mrow").eq(8).should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,1.6667)`); - }); - cy.get(cesc("#\\/cr4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,2.4074)`); - }); - cy.get(cesc("#\\/cr5")).should("not.exist"); - - cy.log("Add fifth point and move to correct location"); - - cy.get(cesc("#\\/addline_button")).click(); - cy.get(cesc("#\\/cr5") + " .mjx-mrow").should( - "contain.text", - `(${xCenter},${yCenter})`, - ); - - cy.window().then(async () => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 4: [2.4, 2.4] }, - sourceDetails: { vertex: 4 }, - }, - }); - }); - - cy.get(cesc("#\\/cr5") + " .mjx-mrow").should( - "contain.text", - `(2.4074,2.4074)`, - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_partial")).should( - "contain.text", - "80%", - ); - cy.get(cesc("#\\/check_cobweb_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("80% correct"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2=2.4074"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(3).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(6) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,2.4074)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(8) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.4074,2.4074)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(10) - .should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,1.6667)`); - }); - cy.get(cesc("#\\/cr4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,2.4074)`); - }); - cy.get(cesc("#\\/cr5") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.4074,2.4074)`); - }); - cy.get(cesc("#\\/cr6")).should("not.exist"); - - cy.log("Add sixth point and move to wrong location"); - - cy.get(cesc("#\\/addline_button")).click(); - cy.get(cesc("#\\/cr6") + " .mjx-mrow").should( - "contain.text", - `(${xCenter},${yCenter})`, - ); - - cy.window().then(async () => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 5: [-1, 3] }, - sourceDetails: { vertex: 5 }, - }, - }); - }); - - cy.get(cesc("#\\/cr6") + " .mjx-mrow").should( - "contain.text", - `(−1,3)`, - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_partial")).should( - "contain.text", - "80%", - ); - cy.get(cesc("#\\/check_cobweb_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("80% correct"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2=2.4074"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(3) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x3=3"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(4).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(6) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,2.4074)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(8) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.4074,2.4074)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(10) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1,3)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(12) - .should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,1.6667)`); - }); - cy.get(cesc("#\\/cr4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,2.4074)`); - }); - cy.get(cesc("#\\/cr5") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.4074,2.4074)`); - }); - cy.get(cesc("#\\/cr6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(−1,3)`); - }); - cy.get(cesc("#\\/cr7")).should("not.exist"); - - cy.log("Move sixth point correct location"); - - cy.window().then(async () => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 5: [2.4, 3] }, - sourceDetails: { vertex: 5 }, - }, - }); - }); - - cy.get(cesc("#\\/cr6") + " .mjx-mrow").should( - "contain.text", - `(2.4074,2.8829)`, - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_correct")).should("be.visible"); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2=2.4074"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(3) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x3=2.8829"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(4).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(6) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,2.4074)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(8) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.4074,2.4074)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(10) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.4074,2.8829)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(12) - .should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,1.6667)`); - }); - cy.get(cesc("#\\/cr4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,2.4074)`); - }); - cy.get(cesc("#\\/cr5") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.4074,2.4074)`); - }); - cy.get(cesc("#\\/cr6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.4074,2.8829)`); - }); - cy.get(cesc("#\\/cr7")).should("not.exist"); - - cy.log("Add seventh point and move to wrong location"); - - cy.get(cesc("#\\/addline_button")).click(); - cy.get(cesc("#\\/cr7") + " .mjx-mrow").should( - "contain.text", - `(${xCenter},${yCenter})`, - ); - - cy.window().then(async () => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 6: [3, 1] }, - sourceDetails: { vertex: 6 }, - }, - }); - }); - - cy.get(cesc("#\\/cr7") + " .mjx-mrow").should( - "contain.text", - `(3,1)`, - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_partial")).should( - "contain.text", - "83%", - ); - cy.get(cesc("#\\/check_cobweb_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("83% correct"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2=2.4074"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(3) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x3=2.8829"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(4).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(6) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,2.4074)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(8) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.4074,2.4074)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(10) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.4074,2.8829)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(12) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,1)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(14) - .should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,1.6667)`); - }); - cy.get(cesc("#\\/cr4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,2.4074)`); - }); - cy.get(cesc("#\\/cr5") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.4074,2.4074)`); - }); - cy.get(cesc("#\\/cr6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.4074,2.8829)`); - }); - cy.get(cesc("#\\/cr7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(3,1)`); - }); - cy.get(cesc("#\\/cr8")).should("not.exist"); - - cy.log("Move seventh point correct location"); - - cy.window().then(async () => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 6: [3, 3] }, - sourceDetails: { vertex: 6 }, - }, - }); - }); - - cy.get(cesc("#\\/cr7") + " .mjx-mrow").should( - "contain.text", - `(2.8829,2.8829)`, - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_correct")).should("be.visible"); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2=2.4074"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(3) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x3=2.8829"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(4).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(6) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,2.4074)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(8) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.4074,2.4074)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(10) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.4074,2.8829)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(12) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.8829,2.8829)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(14) - .should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,1.6667)`); - }); - cy.get(cesc("#\\/cr4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,2.4074)`); - }); - cy.get(cesc("#\\/cr5") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.4074,2.4074)`); - }); - cy.get(cesc("#\\/cr6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.4074,2.8829)`); - }); - cy.get(cesc("#\\/cr7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.8829,2.8829)`); - }); - cy.get(cesc("#\\/cr8")).should("not.exist"); - - cy.log("Add eighth point and move to correct location"); - - cy.get(cesc("#\\/addline_button")).click(); - cy.get(cesc("#\\/cr8") + " .mjx-mrow").should( - "contain.text", - `(${xCenter},${yCenter})`, - ); - - cy.window().then(async () => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/graph1/cobweb", - args: { - pointCoords: { 7: [3, 3] }, - sourceDetails: { vertex: 7 }, - }, - }); - }); - - cy.get(cesc("#\\/cr8") + " .mjx-mrow").should( - "contain.text", - `(2.8829,2.9954)`, - ); - - cy.log("Click submit"); - - cy.get(cesc("#\\/check_cobweb_submit")).click(); - cy.get(cesc("#\\/check_cobweb_correct")).should("be.visible"); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x0=1"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x1=1.6667"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2=2.4074"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(3) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x3=2.8829"); - }); - cy.get(cesc("#\\/_md1")) - .find(".mjx-mtr") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x4=2.9954"); - }); - cy.get(cesc("#\\/_md1")).find(".mjx-mtr").eq(5).should("not.exist"); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,1.6667)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(6) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.6667,2.4074)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(8) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.4074,2.4074)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(10) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.4074,2.8829)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(12) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.8829,2.8829)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(14) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2.8829,2.9954)"); - }); - cy.get(cesc("#\\/psr")) - .find(".mjx-mrow") - .eq(16) - .should("not.exist"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,0)"); - }); - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1.6667)"); - }); - cy.get(cesc("#\\/cr3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,1.6667)`); - }); - cy.get(cesc("#\\/cr4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(1.6667,2.4074)`); - }); - cy.get(cesc("#\\/cr5") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.4074,2.4074)`); - }); - cy.get(cesc("#\\/cr6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.4074,2.8829)`); - }); - cy.get(cesc("#\\/cr7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.8829,2.8829)`); - }); - cy.get(cesc("#\\/cr8") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(2.8829,2.9954)`); - }); - cy.get(cesc("#\\/cr9")).should("not.exist"); - }); - }); - it("cobweb graded applet", () => { cy.window().then(async (win) => { win.postMessage( @@ -2737,75 +892,4 @@ describe("CobwebPolyline Tag Tests", function () { cy.get(cesc2("#/cobwebTutorial/next_button")).should("be.disabled"); cy.get(cesc2("#/ca")).should("have.text", "1"); }); - - it("handle bad initial point, lock to solution", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - x^2 - - -

Initial point:

- - - - -

Vertices: $cobweb.vertices

- - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_p1")).should("have.text", "Initial point: "); - - cy.get(cesc2("#/_p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(_,0)"); - - cy.get(cesc2("#/_p2") + " .mjx-mrow") - .eq(3) - .should("have.text", "(NaN,NaN)"); - - cy.get(cesc2("#/x0") + " textarea").type("0.9{enter}", { force: true }); - - cy.get(cesc2("#/_p2") + " .mjx-mrow").should("contain.text", "(0.9,0)"); - - cy.get(cesc2("#/_p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0.9,0)"); - - cy.get(cesc2("#/_p2") + " .mjx-mrow") - .eq(2) - .should("have.text", "(0.9,0.81)"); - - cy.get(cesc2("#/_p2") + " .mjx-mrow") - .eq(100) - .should("have.text", "(0,0)"); - - cy.get(cesc2("#/x0") + " textarea").type( - "{end}{backspace}{backspace}{backspace}(1.1,3){enter}", - { - force: true, - }, - ); - - cy.get(cesc2("#/_p2") + " .mjx-mrow").should("contain.text", "(1.1,3)"); - - cy.get(cesc2("#/_p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1.1,3)"); - - cy.get(cesc2("#/_p2") + " .mjx-mrow") - .eq(2) - .should("have.text", "(1.1,1.21)"); - - cy.get(cesc2("#/_p2") + " .mjx-mrow") - .eq(100) - .should("have.text", "(∞,∞)"); - }); }); diff --git a/packages/test-cypress/cypress/e2e/dynamicalsystem/equilibriumcurve.cy.js b/packages/test-cypress/cypress/e2e/dynamicalsystem/equilibriumcurve.cy.js deleted file mode 100644 index 62aae3674..000000000 --- a/packages/test-cypress/cypress/e2e/dynamicalsystem/equilibriumcurve.cy.js +++ /dev/null @@ -1,327 +0,0 @@ -import me from "math-expressions"; -import { cesc } from "@doenet/utils"; - -describe("Equilibriumcurve Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("equilibriumcurve change stable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - -

- $(g/A.stable{assignNames="gAs"}) - $(g/B.stable{assignNames="gBs"}) - $(g/C.stable{assignNames="gCs"}) - $(g/D.stable{assignNames="gDs"}) - -

- - $g{name="g2"} - -

- $(g2/A.stable{assignNames="g2As"}) - $(g2/B.stable{assignNames="g2Bs"}) - $(g2/C.stable{assignNames="g2Cs"}) - $(g2/D.stable{assignNames="g2Ds"}) - -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "false"); - cy.get(cesc("#\\/gDs")).should("have.text", "false"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "false"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(false); - expect(stateVariables["/g/D"].stateValues.stable).eq(false); - expect( - stateVariables["/g/A"].stateValues.numericalThroughPoints, - ).eqls([ - [1, 2], - [3, 4], - [2, 6], - ]); - expect( - stateVariables["/g/B"].stateValues.numericalThroughPoints, - ).eqls([ - [3, 2], - [5, 4], - [4, 6], - ]); - expect( - stateVariables["/g/C"].stateValues.numericalThroughPoints, - ).eqls([ - [-3, 2], - [-5, 4], - [-4, 6], - ]); - expect( - stateVariables["/g/D"].stateValues.numericalThroughPoints, - ).eqls([ - [-1, 2], - [-3, 4], - [-2, 6], - ]); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(false); - expect(stateVariables["/g2/D"].stateValues.stable).eq(false); - expect( - stateVariables["/g2/A"].stateValues.numericalThroughPoints, - ).eqls([ - [1, 2], - [3, 4], - [2, 6], - ]); - expect( - stateVariables["/g2/B"].stateValues.numericalThroughPoints, - ).eqls([ - [3, 2], - [5, 4], - [4, 6], - ]); - expect( - stateVariables["/g2/C"].stateValues.numericalThroughPoints, - ).eqls([ - [-3, 2], - [-5, 4], - [-4, 6], - ]); - expect( - stateVariables["/g2/D"].stateValues.numericalThroughPoints, - ).eqls([ - [-1, 2], - [-3, 4], - [-2, 6], - ]); - }); - - cy.log("switch C via boolean input"); - cy.get(cesc("#\\/b1")).click(); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "false"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "false"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(false); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(false); - }); - - cy.log("switch D via boolean input"); - cy.get(cesc("#\\/b2")).click(); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - }); - - cy.log("switch A via first action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchCurve", - componentName: "/g/A", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(false); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(false); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - - cy.get(cesc("#\\/gAs")).should("have.text", "false"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "false"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - }); - - cy.log("switch A via second action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchCurve", - componentName: "/g2/A", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - }); - - cy.log("cannot switch B via action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchCurve", - componentName: "/g/B", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - }); - - cy.log("cannot switch C via second action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchCurve", - componentName: "/g2/C", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - }); - - cy.log("switch D via second action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchCurve", - componentName: "/g2/D", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(false); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(false); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "false"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "false"); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/dynamicalsystem/equilibriumline.cy.js b/packages/test-cypress/cypress/e2e/dynamicalsystem/equilibriumline.cy.js deleted file mode 100644 index 59cea66e4..000000000 --- a/packages/test-cypress/cypress/e2e/dynamicalsystem/equilibriumline.cy.js +++ /dev/null @@ -1,311 +0,0 @@ -import me from "math-expressions"; -import { cesc } from "@doenet/utils"; - -describe("Equilibriumline Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("equilibriumline change stable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - y=4 - y=7 - y=-9 - y=-3 - - - - - -

- $(g/A.stable{assignNames="gAs"}) - $(g/B.stable{assignNames="gBs"}) - $(g/C.stable{assignNames="gCs"}) - $(g/D.stable{assignNames="gDs"}) - -

- - $g{name="g2"} - -

- $(g2/A.stable{assignNames="g2As"}) - $(g2/B.stable{assignNames="g2Bs"}) - $(g2/C.stable{assignNames="g2Cs"}) - $(g2/D.stable{assignNames="g2Ds"}) - -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "false"); - cy.get(cesc("#\\/gDs")).should("have.text", "false"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "false"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(false); - expect(stateVariables["/g/D"].stateValues.stable).eq(false); - expect(stateVariables["/g/A"].stateValues.equation).eqls([ - "=", - "y", - 4, - ]); - expect(stateVariables["/g/B"].stateValues.equation).eqls([ - "=", - "y", - 7, - ]); - expect(stateVariables["/g/C"].stateValues.equation).eqls([ - "=", - "y", - -9, - ]); - expect(stateVariables["/g/D"].stateValues.equation).eqls([ - "=", - "y", - -3, - ]); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(false); - expect(stateVariables["/g2/D"].stateValues.stable).eq(false); - expect(stateVariables["/g2/A"].stateValues.equation).eqls([ - "=", - "y", - 4, - ]); - expect(stateVariables["/g2/B"].stateValues.equation).eqls([ - "=", - "y", - 7, - ]); - expect(stateVariables["/g2/C"].stateValues.equation).eqls([ - "=", - "y", - -9, - ]); - expect(stateVariables["/g2/D"].stateValues.equation).eqls([ - "=", - "y", - -3, - ]); - }); - - cy.log("switch C via boolean input"); - cy.get(cesc("#\\/b1")).click(); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "false"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "false"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(false); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(false); - }); - - cy.log("switch D via boolean input"); - cy.get(cesc("#\\/b2")).click(); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - }); - - cy.log("switch A via first action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchLine", - componentName: "/g/A", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(false); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(false); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - - cy.get(cesc("#\\/gAs")).should("have.text", "false"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "false"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - }); - - cy.log("switch A via second action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchLine", - componentName: "/g2/A", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - }); - - cy.log("cannot switch B via action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchLine", - componentName: "/g/B", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - }); - - cy.log("cannot switch C via second action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchLine", - componentName: "/g2/C", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - }); - - cy.log("switch D via second action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchLine", - componentName: "/g2/D", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(false); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(false); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "false"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "false"); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/dynamicalsystem/equilibriumpoint.cy.js b/packages/test-cypress/cypress/e2e/dynamicalsystem/equilibriumpoint.cy.js deleted file mode 100644 index e5aa9d664..000000000 --- a/packages/test-cypress/cypress/e2e/dynamicalsystem/equilibriumpoint.cy.js +++ /dev/null @@ -1,295 +0,0 @@ -import me from "math-expressions"; -import { cesc } from "@doenet/utils"; - -describe("Equilibriumpoint Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("equilibriumpoint change stable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (4,0) - (7,0) - (-9,0) - (-3,0) - - - - - -

- $(g/A.stable{assignNames="gAs"}) - $(g/B.stable{assignNames="gBs"}) - $(g/C.stable{assignNames="gCs"}) - $(g/D.stable{assignNames="gDs"}) - -

- - $g{name="g2"} - -

- $(g2/A.stable{assignNames="g2As"}) - $(g2/B.stable{assignNames="g2Bs"}) - $(g2/C.stable{assignNames="g2Cs"}) - $(g2/D.stable{assignNames="g2Ds"}) - -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "false"); - cy.get(cesc("#\\/gDs")).should("have.text", "false"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "false"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(false); - expect(stateVariables["/g/D"].stateValues.stable).eq(false); - expect(stateVariables["/g/A"].stateValues.xs.map((x) => x)).eqls([ - 4, 0, - ]); - expect(stateVariables["/g/B"].stateValues.xs.map((x) => x)).eqls([ - 7, 0, - ]); - expect(stateVariables["/g/C"].stateValues.xs.map((x) => x)).eqls([ - -9, 0, - ]); - expect(stateVariables["/g/D"].stateValues.xs.map((x) => x)).eqls([ - -3, 0, - ]); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(false); - expect(stateVariables["/g2/D"].stateValues.stable).eq(false); - expect(stateVariables["/g2/A"].stateValues.xs.map((x) => x)).eqls([ - 4, 0, - ]); - expect(stateVariables["/g2/B"].stateValues.xs.map((x) => x)).eqls([ - 7, 0, - ]); - expect(stateVariables["/g2/C"].stateValues.xs.map((x) => x)).eqls([ - -9, 0, - ]); - expect(stateVariables["/g2/D"].stateValues.xs.map((x) => x)).eqls([ - -3, 0, - ]); - }); - - cy.log("switch C via boolean input"); - cy.get(cesc("#\\/b1")).click(); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "false"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "false"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(false); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(false); - }); - - cy.log("switch D via boolean input"); - cy.get(cesc("#\\/b2")).click(); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - }); - - cy.log("switch A via first action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchPoint", - componentName: "/g/A", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(false); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(false); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - - cy.get(cesc("#\\/gAs")).should("have.text", "false"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "false"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - }); - - cy.log("switch A via second action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchPoint", - componentName: "/g2/A", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - }); - - cy.log("cannot switch B via action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchPoint", - componentName: "/g/B", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - }); - - cy.log("cannot switch C via second action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchPoint", - componentName: "/g2/C", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(true); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(true); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "true"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "true"); - }); - - cy.log("switch D via second action"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "switchPoint", - componentName: "/g2/D", - }); - - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/g/A"].stateValues.stable).eq(true); - expect(stateVariables["/g/B"].stateValues.stable).eq(false); - expect(stateVariables["/g/C"].stateValues.stable).eq(true); - expect(stateVariables["/g/D"].stateValues.stable).eq(false); - - expect(stateVariables["/g2/A"].stateValues.stable).eq(true); - expect(stateVariables["/g2/B"].stateValues.stable).eq(false); - expect(stateVariables["/g2/C"].stateValues.stable).eq(true); - expect(stateVariables["/g2/D"].stateValues.stable).eq(false); - - cy.get(cesc("#\\/gAs")).should("have.text", "true"); - cy.get(cesc("#\\/gBs")).should("have.text", "false"); - cy.get(cesc("#\\/gCs")).should("have.text", "true"); - cy.get(cesc("#\\/gDs")).should("have.text", "false"); - cy.get(cesc("#\\/g2As")).should("have.text", "true"); - cy.get(cesc("#\\/g2Bs")).should("have.text", "false"); - cy.get(cesc("#\\/g2Cs")).should("have.text", "true"); - cy.get(cesc("#\\/g2Ds")).should("have.text", "false"); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/dynamicalsystem/odesystem.cy.js b/packages/test-cypress/cypress/e2e/dynamicalsystem/odesystem.cy.js deleted file mode 100644 index 7f514dba4..000000000 --- a/packages/test-cypress/cypress/e2e/dynamicalsystem/odesystem.cy.js +++ /dev/null @@ -1,2029 +0,0 @@ -import { cesc, createFunctionFromDefinition } from "@doenet/utils"; - -describe("ODEsystem Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("1D linear system", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a =

-

initial condition =

-

tol =

- - $a x - - - - - $ode.numericalsolution{assignNames="f"} - - - -

- - - - -

- - 0 - $tol.value{assignNames="tol2"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdt=xx(0)=1"); - }); - - let ic = 1, - a = 1, - tol = 1e-6; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - - let expectedF = (x) => ic * Math.exp(a * x); - for (let x = 0; x <= 5; x += 0.5) { - expect(solutionF(x)).closeTo( - expectedF(x), - tol * Math.max(1, Math.abs(expectedF(x))), - ); - expect(solutionsFromCore[2 * x]).eq(solutionF(x)); - } - }); - - cy.log("Change initial condition"); - cy.get(cesc("#\\/ic") + " textarea").type(`{end}{backspace}3{enter}`, { - force: true, - }); - - cy.get(cesc("#\\/ode") + " .mjx-mrow").should( - "contain.text", - "dxdt=xx(0)=3", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdt=xx(0)=3"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - ic = 3; - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let expectedF = (x) => ic * Math.exp(a * x); - for (let x = 0; x <= 5; x += 0.5) { - expect(solutionF(x)).closeTo( - expectedF(x), - tol * Math.max(1, Math.abs(expectedF(x))), - ); - expect(solutionsFromCore[2 * x]).eq(solutionF(x)); - } - }); - - cy.log("Change parameter"); - cy.get(cesc("#\\/a") + " textarea").type(`{end}{backspace}-2{enter}`, { - force: true, - }); - - cy.get(cesc("#\\/ode") + " .mjx-mrow").should( - "contain.text", - "dxdt=−2xx(0)=3", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace("−", "-").trim()).equal("dxdt=-2xx(0)=3"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - a = -2; - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let expectedF = (x) => ic * Math.exp(a * x); - for (let x = 0; x <= 5; x += 0.5) { - expect(solutionF(x)).closeTo( - expectedF(x), - tol * Math.max(1, Math.abs(expectedF(x))), - ); - expect(solutionsFromCore[2 * x]).eq(solutionF(x)); - } - }); - - cy.log("Change ic with point"); - cy.window().then(async (win) => { - ic = -5; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { y: ic }, - }); - - let stateVariables = await win.returnAllStateVariables1(); - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let expectedF = (x) => ic * Math.exp(a * x); - for (let x = 0; x <= 5; x += 0.5) { - expect(solutionF(x)).closeTo( - expectedF(x), - tol * Math.max(1, Math.abs(expectedF(x))), - ); - expect(solutionsFromCore[2 * x]).eq(solutionF(x)); - } - }); - - cy.get(cesc("#\\/ode") + " .mjx-mrow").should( - "contain.text", - "dxdt=−2xx(0)=−5", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal("dxdt=-2xx(0)=-5"); - }); - - cy.log("Change tolerance"); - cy.get(cesc("#\\/tol") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}1E-10{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/tol2") + " .mjx-mrow").should( - "contain.text", - "1⋅10−10", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal("dxdt=-2xx(0)=-5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - tol = 1e-10; - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let expectedF = (x) => ic * Math.exp(a * x); - for (let x = 0; x <= 5; x += 0.5) { - expect(solutionF(x)).closeTo( - expectedF(x), - tol * Math.max(1, Math.abs(expectedF(x))), - ); - expect(solutionsFromCore[2 * x]).eq(solutionF(x)); - } - }); - - cy.log("Change parameter again"); - cy.get(cesc("#\\/a") + " textarea").type( - `{end}{backspace}{backspace}0.5{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/ode") + " .mjx-mrow").should( - "contain.text", - "dxdt=0.5xx(0)=−5", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal( - "dxdt=0.5xx(0)=-5", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - a = 0.5; - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let expectedF = (x) => ic * Math.exp(a * x); - for (let x = 0; x <= 5; x += 0.5) { - expect(solutionF(x)).closeTo( - expectedF(x), - tol * Math.max(1, Math.abs(expectedF(x))), - ); - expect(solutionsFromCore[2 * x]).eq(solutionF(x)); - } - }); - - cy.log("Change initial condition to zero"); - cy.get(cesc("#\\/ic") + " textarea").type( - `{end}{backspace}{backspace}0{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/ode") + " .mjx-mrow").should( - "contain.text", - "dxdt=0.5xx(0)=0", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-").trim()).equal("dxdt=0.5xx(0)=0"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - for (let x = 0; x <= 1000; x += 100) { - expect(solutionF(x)).eq(0); - } - for (let x = 0; x <= 5; x += 0.5) { - expect(solutionsFromCore[2 * x]).eq(0); - } - }); - }); - - it("effect of max iterations, chunksize", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

tol =

-

T =

-

maxiter =

-

chunksize =

- - x - - -

f($T) = $$(ode.numericalSolution)($T) -

- - - $tol.value{assignNames="tol2"} - $T.value{assignNames="T2"} - $maxiter.value{assignNames="maxiter2"} - $chunksize.value{assignNames="chunksize2"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let tol = 1e-6; - let expectedF = (x) => Math.exp(x); - - cy.get(cesc("#\\/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text.split("=")[1])).closeTo( - expectedF(10), - tol * expectedF(10), - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - for (let x = 0; x <= 10; x += 1) { - expect(solutionF(x)).closeTo( - expectedF(x), - tol * Math.max(1, Math.abs(expectedF(x))), - ); - } - }); - - cy.log("Can't make it to t=20"); - cy.get(cesc("#\\/T") + " textarea").type( - `{end}{backspace}{backspace}20{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/T2") + " .mjx-mrow").should("contain.text", "20"); - cy.get(cesc("#\\/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.split("=")[1].trim()).eq("NaN"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - assert.isNaN(solutionF(20)); - }); - - cy.log("increase maxiterations"); - cy.get(cesc("#\\/maxiter") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}2000{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/maxiter2") + " .mjx-mrow").should( - "contain.text", - "2000", - ); - cy.get(cesc("#\\/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text.split("=")[1])).closeTo( - expectedF(20), - tol * expectedF(20), - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - for (let x = 0; x <= 20; x += 1) { - expect(solutionF(x)).closeTo( - expectedF(x), - tol * Math.max(1, Math.abs(expectedF(x))), - ); - } - }); - - cy.log("Can't make it if decrease tolerance"); - cy.get(cesc("#\\/tol") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}1E-8{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/tol2") + " .mjx-mrow").should( - "contain.text", - "1⋅10−8", - ); - cy.get(cesc("#\\/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.split("=")[1].trim()).eq("NaN"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - assert.isNaN(solutionF(20)); - }); - - cy.log("increase maxiterations further"); - cy.get(cesc("#\\/maxiter") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}5000{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/maxiter2") + " .mjx-mrow").should( - "contain.text", - "5000", - ); - cy.get(cesc("#\\/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text.split("=")[1])).closeTo( - expectedF(20), - tol * expectedF(20), - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - for (let x = 0; x <= 20; x += 1) { - expect(solutionF(x)).closeTo( - expectedF(x), - tol * Math.max(1, Math.abs(expectedF(x))), - ); - } - }); - - cy.log("decrease maxiterations back down"); - cy.get(cesc("#\\/maxiter") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}1000{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/maxiter2") + " .mjx-mrow").should( - "contain.text", - "1000", - ); - cy.get(cesc("#\\/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.split("=")[1].trim()).eq("NaN"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - assert.isNaN(solutionF(20)); - }); - - cy.log("decrease chunksize"); - cy.get(cesc("#\\/chunksize") + " textarea").type( - `{end}{backspace}{backspace}1{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/chunksize2") + " .mjx-mrow").should( - "not.contain.text", - "10", - ); - cy.get(cesc("#\\/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text.split("=")[1])).closeTo( - expectedF(20), - tol * expectedF(20), - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - for (let x = 0; x <= 20; x += 1) { - expect(solutionF(x)).closeTo( - expectedF(x), - tol * Math.max(1, Math.abs(expectedF(x))), - ); - } - }); - }); - - it("change variables 1D", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

independent variable =

-

dependent variable =

- - - $dvar - - - - $ode.numericalsolution{assignNames="f"} - - - -

- - - - -

- - $ivar.value{assignNames="ivar2"} - $dvar.value{assignNames="dvar2"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let tol = 1e-6; - let expectedF = (x) => Math.exp(x); - - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdt=xx(0)=1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - - expect(solutionF(0)).eq(1); - expect(solutionsFromCore[0]).eq(1); - for (let t = 1; t <= 5; t += 1) { - expect(solutionF(t)).closeTo( - expectedF(t), - tol * Math.max(1, Math.abs(expectedF(t))), - ); - expect(solutionsFromCore[t]).eq(solutionF(t)); - } - }); - - cy.log("change independent variable"); - cy.get(cesc("#\\/ivar") + " textarea").type( - `{end}{backspace}s{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/ivar2") + " .mjx-mrow").should("contain.text", "s"); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxds=xx(0)=1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - expect(solutionF(0)).eq(1); - expect(solutionsFromCore[0]).eq(1); - for (let t = 1; t <= 5; t += 1) { - expect(solutionF(t)).closeTo( - expectedF(t), - tol * Math.max(1, Math.abs(expectedF(t))), - ); - expect(solutionsFromCore[t]).eq(solutionF(t)); - } - }); - - cy.log("erase independent variable"); - cy.get(cesc("#\\/ivar") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); - - cy.get(cesc("#\\/ivar2") + " .mjx-mrow").should("contain.text", "_"); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxd_=xx(0)=1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - expect(solutionF(0)).eq(1); - expect(solutionsFromCore[0]).eq(1); - for (let t = 1; t <= 5; t += 1) { - assert.isNaN(solutionF(t)); - assert.isNaN(solutionsFromCore[t]); - } - }); - - cy.log("restore independent variable"); - cy.get(cesc("#\\/ivar") + " textarea").type( - "{end}{backspace}u{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/ivar2") + " .mjx-mrow").should("contain.text", "u"); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdu=xx(0)=1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - expect(solutionF(0)).eq(1); - expect(solutionsFromCore[0]).eq(1); - for (let t = 1; t <= 5; t += 1) { - expect(solutionF(t)).closeTo( - expectedF(t), - tol * Math.max(1, Math.abs(expectedF(t))), - ); - expect(solutionsFromCore[t]).eq(solutionF(t)); - } - }); - - cy.log("invalid independent variable"); - cy.get(cesc("#\\/ivar") + " textarea").type( - "{end}{backspace}1{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/ivar2") + " .mjx-mrow").should("contain.text", "1"); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxd1=xx(0)=1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - expect(solutionF(0)).eq(1); - expect(solutionsFromCore[0]).eq(1); - for (let t = 1; t <= 5; t += 1) { - assert.isNaN(solutionF(t)); - assert.isNaN(solutionsFromCore[t]); - } - }); - - cy.log("restore independent variable"); - cy.get(cesc("#\\/ivar") + " textarea").type( - "{end}{backspace}v{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/ivar2") + " .mjx-mrow").should("contain.text", "v"); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdv=xx(0)=1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - expect(solutionF(0)).eq(1); - expect(solutionsFromCore[0]).eq(1); - for (let t = 1; t <= 5; t += 1) { - expect(solutionF(t)).closeTo( - expectedF(t), - tol * Math.max(1, Math.abs(expectedF(t))), - ); - expect(solutionsFromCore[t]).eq(solutionF(t)); - } - }); - - cy.log("change dependent variable"); - cy.get(cesc("#\\/dvar") + " textarea").type( - "{end}{backspace}z{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/dvar2") + " .mjx-mrow").should("contain.text", "z"); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dzdv=zz(0)=1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - expect(solutionF(0)).eq(1); - expect(solutionsFromCore[0]).eq(1); - for (let t = 1; t <= 5; t += 1) { - expect(solutionF(t)).closeTo( - expectedF(t), - tol * Math.max(1, Math.abs(expectedF(t))), - ); - expect(solutionsFromCore[t]).eq(solutionF(t)); - } - }); - - cy.log("duplicate variable"); - cy.get(cesc("#\\/dvar") + " textarea").type( - "{end}{backspace}v{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/dvar2") + " .mjx-mrow").should("contain.text", "v"); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dvdv=vv(0)=1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - expect(solutionF(0)).eq(1); - expect(solutionsFromCore[0]).eq(1); - for (let t = 1; t <= 5; t += 1) { - assert.isNaN(solutionF(t)); - assert.isNaN(solutionsFromCore[t]); - } - }); - - cy.log("different dependent variable"); - cy.get(cesc("#\\/dvar") + " textarea").type( - "{end}{backspace}v_1{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/dvar2") + " .mjx-mrow").should("contain.text", "v1"); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dv1dv=v1v1(0)=1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - expect(solutionF(0)).eq(1); - expect(solutionsFromCore[0]).eq(1); - for (let t = 1; t <= 5; t += 1) { - expect(solutionF(t)).closeTo( - expectedF(t), - tol * Math.max(1, Math.abs(expectedF(t))), - ); - expect(solutionsFromCore[t]).eq(solutionF(t)); - } - }); - - cy.log("invalid dependent variable"); - cy.get(cesc("#\\/dvar") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}ab{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/dvar2") + " .mjx-mrow").should("contain.text", "ab"); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dabdv=abab(0)=1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - expect(solutionF(0)).eq(1); - expect(solutionsFromCore[0]).eq(1); - for (let t = 1; t <= 5; t += 1) { - assert.isNaN(solutionF(t)); - assert.isNaN(solutionsFromCore[t]); - } - }); - - cy.log("restore dependent variable"); - cy.get(cesc("#\\/dvar") + " textarea").type( - "{end}{backspace}{backspace}a{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/dvar2") + " .mjx-mrow").should( - "not.contain.text", - "ab", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dadv=aa(0)=1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let solutionF = createFunctionFromDefinition( - stateVariables["/ode"].stateValues - .numericalSolutionFDefinitions[0], - ); - let solutionsFromCore = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - expect(solutionF(0)).eq(1); - expect(solutionsFromCore[0]).eq(1); - for (let t = 1; t <= 5; t += 1) { - expect(solutionF(t)).closeTo( - expectedF(t), - tol * Math.max(1, Math.abs(expectedF(t))), - ); - expect(solutionsFromCore[t]).eq(solutionF(t)); - } - }); - }); - - it("display digits", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

displaydigits =

- - - 0.123456789123456789x - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdt=0.1234567891xx(0)=9.87654322"); - }); - - cy.log("change display digits"); - cy.get(cesc("#\\/digits") + " textarea").type( - "{end}{backspace}{backspace}2{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/ode") + " .mjx-mrow").should( - "contain.text", - "dxdt=0.12xx(0)=9.9", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdt=0.12xx(0)=9.9"); - }); - - cy.log("change display digits again"); - cy.get(cesc("#\\/digits") + " textarea").type( - "{end}{backspace}14{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/ode") + " .mjx-mrow").should( - "contain.text", - "dxdt=0.12345678912346xx(0)=9.8765432198765", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "dxdt=0.12345678912346xx(0)=9.8765432198765", - ); - }); - }); - - it("initial independent variable value", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

initial t =

-

final t =

- - - x - - -

We started with - x($ode.initialindependentvariablevalue) = 1.

- -

We end with - x($tf) = $$(ode.numericalSolution)($tf)

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdt=xx(0)=1"); - }); - - cy.get(cesc("#\\/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x(0)=1"); - }); - - cy.get(cesc("#\\/_m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.split("=")[0].trim()).equal("x(10)"); - expect(Number(text.split("=")[1])).closeTo( - Math.exp(10), - 1e-6 * Math.exp(10), - ); - }); - - cy.log("Change initial time"); - cy.get(cesc("#\\/t0") + " textarea").type("{end}{backspace}-5{enter}", { - force: true, - }); - - cy.get(cesc("#\\/ode") + " .mjx-mrow").should( - "contain.text", - "dxdt=xx(−5)=1", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdt=xx(−5)=1"); - }); - - cy.get(cesc("#\\/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x(−5)=1"); - }); - - cy.get(cesc("#\\/_m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.split("=")[0].trim()).equal("x(10)"); - expect(Number(text.split("=")[1])).closeTo( - Math.exp(15), - 1e-6 * Math.exp(15), - ); - }); - - cy.log("Change initial and final time"); - cy.get(cesc("#\\/tf") + " textarea").type( - "{end}{backspace}{backspace}12{enter}", - { force: true }, - ); - cy.get(cesc("#\\/t0") + " textarea").type( - "{end}{backspace}{backspace}11{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/ode") + " .mjx-mrow").should( - "contain.text", - "dxdt=xx(11)=1", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdt=xx(11)=1"); - }); - - cy.get(cesc("#\\/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x(11)=1"); - }); - - cy.get(cesc("#\\/_m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.split("=")[0].trim()).equal("x(12)"); - expect(Number(text.split("=")[1])).closeTo( - Math.exp(1), - 1e-6 * Math.exp(1), - ); - }); - }); - - it("display initial conditions", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

display initial conditions:

- - x - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdt=xx(0)=1"); - }); - - cy.log("don't display initial conditions"); - cy.get(cesc("#\\/showic")).click(); - cy.get(cesc("#\\/ode") + " .mjx-mrow").should("contain.text", "dxdt=x"); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdt=x"); - }); - - cy.log("display initial conditions again"); - cy.get(cesc("#\\/showic")).click(); - cy.get(cesc("#\\/ode") + " .mjx-mrow").should( - "contain.text", - "dxdt=xx(0)=1", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdt=xx(0)=1"); - }); - }); - - it("2D linear system", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

initial condition 1 =

-

initial condition 2 =

- - -0.2y - 0.1x + 0.3y - - - - - $ode.numericalsolutions{assignNames="f1 f2"} - - - - -

- - - - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let tol = 1e-6; - - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - "dxdt=-0.2ydydt=0.1x+0.3yx(0)=1y(0)=3", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let ode = stateVariables["/ode"]; - let solutionFx = createFunctionFromDefinition( - ode.stateValues.numericalSolutionFDefinitions[0], - ); - let solutionFy = createFunctionFromDefinition( - ode.stateValues.numericalSolutionFDefinitions[1], - ); - let solutionFx2 = createFunctionFromDefinition( - stateVariables["/f1"].stateValues.fDefinitions[0], - ); - let solutionFy2 = createFunctionFromDefinition( - stateVariables["/f2"].stateValues.fDefinitions[0], - ); - let solutionsFromCoreX = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let solutionsFromCoreY = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[1] - .componentName - ].stateValues.value, - ); - let expectedFx = (t) => - 8 * Math.exp(0.1 * t) - 7 * Math.exp(0.2 * t); - let expectedFy = (t) => - -4 * Math.exp(0.1 * t) + 7 * Math.exp(0.2 * t); - for (let t = 0; t <= 10; t += 1) { - expect(solutionFx(t)).closeTo( - expectedFx(t), - tol * Math.max(1, Math.abs(expectedFx(t))), - ); - expect(solutionFy(t)).closeTo( - expectedFy(t), - tol * Math.max(1, Math.abs(expectedFy(t))), - ); - expect(solutionFx2(t)).eq(solutionFx(t)); - expect(solutionFy2(t)).eq(solutionFy(t)); - expect(solutionsFromCoreX[t]).eq(solutionFx(t)); - expect(solutionsFromCoreY[t]).eq(solutionFy(t)); - } - }); - - cy.log("Change initial condition"); - cy.get(cesc("#\\/ic1") + " textarea").type(`{end}{backspace}3{enter}`, { - force: true, - }); - cy.get(cesc("#\\/ic2") + " textarea").type( - `{end}{backspace}-1{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/ode") + " .mjx-mrow").should( - "contain.text", - "dxdt=−0.2ydydt=0.1x+0.3yx(0)=3y(0)=−1", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - "dxdt=-0.2ydydt=0.1x+0.3yx(0)=3y(0)=-1", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let ode = stateVariables["/ode"]; - let solutionFx = createFunctionFromDefinition( - ode.stateValues.numericalSolutionFDefinitions[0], - ); - let solutionFy = createFunctionFromDefinition( - ode.stateValues.numericalSolutionFDefinitions[1], - ); - let solutionFx2 = createFunctionFromDefinition( - stateVariables["/f1"].stateValues.fDefinitions[0], - ); - let solutionFy2 = createFunctionFromDefinition( - stateVariables["/f2"].stateValues.fDefinitions[0], - ); - let solutionsFromCoreX = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let solutionsFromCoreY = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[1] - .componentName - ].stateValues.value, - ); - let expectedFx = (t) => - 4 * Math.exp(0.1 * t) - 1 * Math.exp(0.2 * t); - let expectedFy = (t) => - -2 * Math.exp(0.1 * t) + 1 * Math.exp(0.2 * t); - for (let t = 0; t <= 10; t += 1) { - expect(solutionFx(t)).closeTo( - expectedFx(t), - tol * Math.max(1, Math.abs(expectedFx(t))), - ); - expect(solutionFy(t)).closeTo( - expectedFy(t), - tol * Math.max(1, Math.abs(expectedFy(t))), - ); - expect(solutionFx2(t)).eq(solutionFx(t)); - expect(solutionFy2(t)).eq(solutionFy(t)); - expect(solutionsFromCoreX[t]).eq(solutionFx(t)); - expect(solutionsFromCoreY[t]).eq(solutionFy(t)); - } - }); - - cy.log("Change ic with point"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: -5, y: 2 }, - }); - - let stateVariables = await win.returnAllStateVariables1(); - - let ode = stateVariables["/ode"]; - let solutionFx = createFunctionFromDefinition( - ode.stateValues.numericalSolutionFDefinitions[0], - ); - let solutionFy = createFunctionFromDefinition( - ode.stateValues.numericalSolutionFDefinitions[1], - ); - let solutionFx2 = createFunctionFromDefinition( - stateVariables["/f1"].stateValues.fDefinitions[0], - ); - let solutionFy2 = createFunctionFromDefinition( - stateVariables["/f2"].stateValues.fDefinitions[0], - ); - let solutionsFromCoreX = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let solutionsFromCoreY = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[1] - .componentName - ].stateValues.value, - ); - let expectedFx = (t) => - -6 * Math.exp(0.1 * t) + 1 * Math.exp(0.2 * t); - let expectedFy = (t) => - 3 * Math.exp(0.1 * t) - 1 * Math.exp(0.2 * t); - for (let t = 0; t <= 10; t += 1) { - expect(solutionFx(t)).closeTo( - expectedFx(t), - tol * Math.max(1, Math.abs(expectedFx(t))), - ); - expect(solutionFy(t)).closeTo( - expectedFy(t), - tol * Math.max(1, Math.abs(expectedFy(t))), - ); - expect(solutionFx2(t)).eq(solutionFx(t)); - expect(solutionFy2(t)).eq(solutionFy(t)); - expect(solutionsFromCoreX[t]).eq(solutionFx(t)); - expect(solutionsFromCoreY[t]).eq(solutionFy(t)); - } - }); - - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - "dxdt=-0.2ydydt=0.1x+0.3yx(0)=-5y(0)=2", - ); - }); - - cy.log("Change initial condition to zero"); - cy.get(cesc("#\\/ic1") + " textarea").type( - `{end}{backspace}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/ic2") + " textarea").type(`{end}{backspace}0{enter}`, { - force: true, - }); - - cy.get(cesc("#\\/ode") + " .mjx-mrow").should( - "contain.text", - "dxdt=−0.2ydydt=0.1x+0.3yx(0)=0y(0)=0", - ); - cy.get(cesc("#\\/ode")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - "dxdt=-0.2ydydt=0.1x+0.3yx(0)=0y(0)=0", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let ode = stateVariables["/ode"]; - let solutionFx = createFunctionFromDefinition( - ode.stateValues.numericalSolutionFDefinitions[0], - ); - let solutionFy = createFunctionFromDefinition( - ode.stateValues.numericalSolutionFDefinitions[1], - ); - let solutionFx2 = createFunctionFromDefinition( - stateVariables["/f1"].stateValues.fDefinitions[0], - ); - let solutionFy2 = createFunctionFromDefinition( - stateVariables["/f2"].stateValues.fDefinitions[0], - ); - let solutionsFromCoreX = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let solutionsFromCoreY = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[1] - .componentName - ].stateValues.value, - ); - for (let t = 0; t <= 10; t += 1) { - expect(solutionFx(t)).eq(0); - expect(solutionFy(t)).eq(0); - expect(solutionFx2(t)).eq(solutionFx(t)); - expect(solutionFy2(t)).eq(solutionFy(t)); - expect(solutionsFromCoreX[t]).eq(solutionFx(t)); - expect(solutionsFromCoreY[t]).eq(solutionFy(t)); - } - }); - }); - - it("higher dimensional ode", () => { - cy.log("no variables specified"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - q - r - s - u - v - w - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let disp = function (vs, rs, is) { - let s = ""; - for (let i = 0; i < vs.length; i++) { - s += "d" + vs[i] + "dt=" + rs[i]; - } - for (let i = 0; i < vs.length; i++) { - s += vs[i] + "(0)=" + is[i]; - } - return s; - }; - - let vs = ["x1", "x2", "x3", "x4", "x5", "x6"]; - let rs = ["q", "r", "s", "u", "v", "w"]; - let is = ["a", "b", "c", "d", "e", "f"]; - - cy.get(cesc("#\\/_odesystem1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(disp(vs, rs, is)); - }); - - cy.log("all variables specified"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - b - - q - r - s - u - v - w - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "b"); // to wait for page to load - - let vs2 = ["j", "k", "l", "m", "n", "p"]; - - cy.get(cesc("#\\/_odesystem1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(disp(vs2, rs, is)); - }); - - cy.log("some variables specified"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - c - - q - r - s - u - v - w - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "c"); // to wait for page to load - - let vs3 = ["j", "k", "l", "x4", "x5", "x6"]; - - cy.get(cesc("#\\/_odesystem1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(disp(vs3, rs, is)); - }); - }); - - it("copy righthandside, initial conditions", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - a*x*y+z - x/y - - -

RHS1: $ode.rhs1{name="rhs1a"}

-

RHS2: $ode.rhs2{name="rhs2a"}

-

RHS1: $ode.rhs{name="rhs1b"}

-

Both RHSs: $ode.rhss{name="rhssa"}

-

RHS1: $ode.righthandside1{name="rhs1c"}

-

RHS2: $ode.righthandside2{name="rhs2b"}

-

RHS1: $ode.righthandside{name="rhs1d"}

-

Both RHSs: $ode.righthandsides{name="rhssb"}

- -

IC1: $ode.initialcondition1{name="ic1a"}

-

IC2: $ode.initialcondition2{name="ic2a"}

-

IC1: $ode.initialcondition{name="ic1b"}

-

Both ICs: $ode.initialconditions{name="icsa"}

- -

Swap right hand sides and keep initial conditions

- - - $ode.rhs2 - $ode.rhs1 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("axy+z"); - }); - cy.get(cesc("#\\/_p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc("#\\/_p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("axy+z"); - }); - cy.get(cesc("#\\/_p4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("axy+z"); - }); - cy.get(cesc("#\\/_p4") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc("#\\/_p5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("axy+z"); - }); - cy.get(cesc("#\\/_p6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc("#\\/_p7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("axy+z"); - }); - cy.get(cesc("#\\/_p8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("axy+z"); - }); - cy.get(cesc("#\\/_p8") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc("#\\/_p9")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/_p10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/_p11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/_p12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/_p12") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - - cy.get(cesc("#\\/odeswap")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("dxdt=xydydt=axy+zx(0)=cy(0)=3"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let rhs1tree = ["+", ["*", "a", "x", "y"], "z"]; - let rhs2tree = ["/", "x", "y"]; - expect( - stateVariables[ - stateVariables["/rhs1a"].replacements[0].componentName - ].stateValues.value, - ).eqls(rhs1tree); - expect( - stateVariables[ - stateVariables["/rhs1b"].replacements[0].componentName - ].stateValues.value, - ).eqls(rhs1tree); - expect( - stateVariables[ - stateVariables["/rhs1c"].replacements[0].componentName - ].stateValues.value, - ).eqls(rhs1tree); - expect( - stateVariables[ - stateVariables["/rhs1d"].replacements[0].componentName - ].stateValues.value, - ).eqls(rhs1tree); - expect( - stateVariables[ - stateVariables["/rhs2a"].replacements[0].componentName - ].stateValues.value, - ).eqls(rhs2tree); - expect( - stateVariables[ - stateVariables["/rhs2b"].replacements[0].componentName - ].stateValues.value, - ).eqls(rhs2tree); - expect( - stateVariables[ - stateVariables["/rhssa"].replacements[0].componentName - ].stateValues.value, - ).eqls(rhs1tree); - expect( - stateVariables[ - stateVariables["/rhssa"].replacements[1].componentName - ].stateValues.value, - ).eqls(rhs2tree); - expect( - stateVariables[ - stateVariables["/rhssb"].replacements[0].componentName - ].stateValues.value, - ).eqls(rhs1tree); - expect( - stateVariables[ - stateVariables["/rhssb"].replacements[1].componentName - ].stateValues.value, - ).eqls(rhs2tree); - expect( - stateVariables[ - stateVariables["/ic1a"].replacements[0].componentName - ].stateValues.value, - ).eqls("c"); - expect( - stateVariables[ - stateVariables["/ic1b"].replacements[0].componentName - ].stateValues.value, - ).eqls("c"); - expect( - stateVariables[ - stateVariables["/ic2a"].replacements[0].componentName - ].stateValues.value, - ).eqls(3); - expect( - stateVariables[ - stateVariables["/icsa"].replacements[0].componentName - ].stateValues.value, - ).eqls("c"); - expect( - stateVariables[ - stateVariables["/icsa"].replacements[1].componentName - ].stateValues.value, - ).eqls(3); - }); - }); - - it("warnings", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -a - - 5y - - - - 5y - - - - 5y - - - - 5x - 3x - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(4); - - expect(errorWarnings.warnings[0].message).contain( - `Invalid value of a variable: sin(x)`, - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(7); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(47); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(7); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(52); - - expect(errorWarnings.warnings[1].message).contain( - `Variables of must be different than independent variable`, - ); - expect(errorWarnings.warnings[1].level).eq(1); - expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(3); - expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(1); - expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(5); - expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(12); - - expect(errorWarnings.warnings[2].message).contain( - `Invalid value of a variable: sin(y)`, - ); - expect(errorWarnings.warnings[2].level).eq(1); - expect(errorWarnings.warnings[2].doenetMLrange.lineBegin).eq(11); - expect(errorWarnings.warnings[2].doenetMLrange.charBegin).eq(23); - expect(errorWarnings.warnings[2].doenetMLrange.lineEnd).eq(11); - expect(errorWarnings.warnings[2].doenetMLrange.charEnd).eq(28); - - expect(errorWarnings.warnings[3].message).contain( - `Can't define ODE RHS functions with duplicate dependent variable names`, - ); - expect(errorWarnings.warnings[3].level).eq(1); - expect(errorWarnings.warnings[3].doenetMLrange.lineBegin).eq(15); - expect(errorWarnings.warnings[3].doenetMLrange.charBegin).eq(1); - expect(errorWarnings.warnings[3].doenetMLrange.lineEnd).eq(18); - expect(errorWarnings.warnings[3].doenetMLrange.charEnd).eq(12); - }); - }); -});