From b0c8eccfd115c32f2c3aed0625f73ef77582557c Mon Sep 17 00:00:00 2001 From: Duane Nykamp Date: Mon, 14 Oct 2024 23:10:41 -0500 Subject: [PATCH] convert substitute tests to vitest --- .../src/test/tagSpecific/copy.test.ts | 4 - .../src/test/tagSpecific/function.test.ts | 144 +- .../src/test/tagSpecific/substitute.test.ts | 1586 +++++++++ .../cypress/e2e/tagSpecific/substitute.cy.js | 2853 ----------------- 4 files changed, 1650 insertions(+), 2937 deletions(-) create mode 100644 packages/doenetml-worker/src/test/tagSpecific/substitute.test.ts delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/substitute.cy.js diff --git a/packages/doenetml-worker/src/test/tagSpecific/copy.test.ts b/packages/doenetml-worker/src/test/tagSpecific/copy.test.ts index fbaccfb31..689aec71a 100644 --- a/packages/doenetml-worker/src/test/tagSpecific/copy.test.ts +++ b/packages/doenetml-worker/src/test/tagSpecific/copy.test.ts @@ -7383,8 +7383,6 @@ describe("Copy tag tests", async () => { let P21Dec4 = round({ val: P21, decimals: 4 }); let P22Dec4 = round({ val: P22, decimals: 4 }); - console.log({ P11Dig2 }); - const stateVariables = await returnAllStateVariables(core); expect(stateVariables["/p1"].stateValues.text).eq( @@ -8589,8 +8587,6 @@ describe("Copy tag tests", async () => { expect(stateVariables["/num"].stateValues.value).eqls(NaN); - console.log(tiName); - await updateMathInputValue({ latex: "4", componentName: tiName, core }); await core.requestAction({ componentName: "/ans", diff --git a/packages/doenetml-worker/src/test/tagSpecific/function.test.ts b/packages/doenetml-worker/src/test/tagSpecific/function.test.ts index 20e8f5581..b8a111023 100644 --- a/packages/doenetml-worker/src/test/tagSpecific/function.test.ts +++ b/packages/doenetml-worker/src/test/tagSpecific/function.test.ts @@ -1,18 +1,18 @@ import { describe, expect, it, vi } from "vitest"; import { createTestCore, returnAllStateVariables } from "../utils/test-core"; import { cleanLatex } from "../utils/math"; -import { - updateBooleanInputValue, - updateMathInputValue, - updateMatrixInputValue, - updateTextInputValue, -} from "../utils/actions"; +import { updateMathInputValue } from "../utils/actions"; import { createFunctionFromDefinition } from "@doenet/utils"; import me from "math-expressions"; const Mock = vi.fn(); vi.stubGlobal("postMessage", Mock); +function constantFromAst(tree) { + //@ts-ignore + return me.fromAst(tree).evaluate_to_constant(); +} + describe("Function tag tests", async () => { it("function with nothing", async () => { let core = await createTestCore({ @@ -1070,8 +1070,8 @@ describe("Function tag tests", async () => { let p = stateVariables["/P"]; - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + let x = constantFromAst(p.stateValues.xs[0]); + let y = constantFromAst(p.stateValues.xs[1]); expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); @@ -1087,9 +1087,9 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; // @ts-ignore - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); // @ts-ignore - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + y = constantFromAst(p.stateValues.xs[1]); expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); @@ -1105,9 +1105,9 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; // @ts-ignore - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); // @ts-ignore - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + y = constantFromAst(p.stateValues.xs[1]); expect(6 - (x - 5) * (x - 5) * (2 / 9)).closeTo(y, 1e-5); }); @@ -1131,14 +1131,11 @@ describe("Function tag tests", async () => { let p = stateVariables["/P"]; - expect(me.fromAst(p.stateValues.xs[0]).evaluate_to_constant()).closeTo( + expect(constantFromAst(p.stateValues.xs[0])).closeTo( Math.sqrt(2), 1e-6, ); - expect(me.fromAst(p.stateValues.xs[1]).evaluate_to_constant()).closeTo( - 2, - 1e-6, - ); + expect(constantFromAst(p.stateValues.xs[1])).closeTo(2, 1e-6); await core.requestAction({ actionName: "movePoint", @@ -1151,14 +1148,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - expect(me.fromAst(p.stateValues.xs[0]).evaluate_to_constant()).closeTo( - -2, - 1e-6, - ); - expect(me.fromAst(p.stateValues.xs[1]).evaluate_to_constant()).closeTo( - 4, - 1e-6, - ); + expect(constantFromAst(p.stateValues.xs[0])).closeTo(-2, 1e-6); + expect(constantFromAst(p.stateValues.xs[1])).closeTo(4, 1e-6); }); it("point constrained to function, restrict to closed domain", async () => { @@ -1179,8 +1170,8 @@ describe("Function tag tests", async () => { let p = stateVariables["/P"]; - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + let x = constantFromAst(p.stateValues.xs[0]); + let y = constantFromAst(p.stateValues.xs[1]); expect(x).closeTo(1, 1e-12); expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); @@ -1196,8 +1187,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(x).closeTo(-4, 1e-12); expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); @@ -1213,8 +1204,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(x).closeTo(6, 1e-12); expect(6 - (x - 5) * (x - 5) * (2 / 9)).closeTo(y, 1e-5); @@ -1230,8 +1221,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(x).closeTo(7, 1e-12); expect(6 - (x - 5) * (x - 5) * (2 / 9)).closeTo(y, 1e-5); @@ -1255,8 +1246,8 @@ describe("Function tag tests", async () => { let p = stateVariables["/P"]; - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + let x = constantFromAst(p.stateValues.xs[0]); + let y = constantFromAst(p.stateValues.xs[1]); expect(x).closeTo(1, 1e-12); expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); @@ -1272,8 +1263,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(x).greaterThan(-4 + 1e-12); expect(x).lessThan(-4 + 1e-3); @@ -1290,8 +1281,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(x).closeTo(6, 1e-12); expect(6 - (x - 5) * (x - 5) * (2 / 9)).closeTo(y, 1e-5); @@ -1307,8 +1298,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(x).lessThan(7 - 1e-12); expect(x).greaterThan(7 - 1e-3); @@ -1321,14 +1312,8 @@ describe("Function tag tests", async () => { let stateVariables = await returnAllStateVariables(core); let p = stateVariables["/P"]; - expect(me.fromAst(p.stateValues.xs[0]).evaluate_to_constant()).closeTo( - 1, - 1e-6, - ); - expect(me.fromAst(p.stateValues.xs[1]).evaluate_to_constant()).closeTo( - f(1), - 1e-6, - ); + expect(constantFromAst(p.stateValues.xs[0])).closeTo(1, 1e-6); + expect(constantFromAst(p.stateValues.xs[1])).closeTo(f(1), 1e-6); await core.requestAction({ actionName: "movePoint", @@ -1341,10 +1326,9 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + let x = constantFromAst(p.stateValues.xs[0]); + let y = constantFromAst(p.stateValues.xs[1]); - console.log({ x, y }); expect(y).closeTo(f(x), 1e-6); await core.requestAction({ @@ -1358,8 +1342,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(y).closeTo(f(x), 1e-6); @@ -1374,8 +1358,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(y).closeTo(f(x), 1e-6); @@ -1390,8 +1374,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(y).closeTo(f(x), 1e-6); } @@ -1744,8 +1728,8 @@ describe("Function tag tests", async () => { let p = stateVariables["/P"]; - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + let x = constantFromAst(p.stateValues.xs[0]); + let y = constantFromAst(p.stateValues.xs[1]); expect(Math.log(2 * x)).closeTo(y, 1e-5); @@ -1760,8 +1744,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(Math.log(2 * x)).closeTo(y, 1e-5); @@ -1776,8 +1760,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(Math.log(2 * x)).closeTo(y, 1e-5); }); @@ -1802,8 +1786,8 @@ describe("Function tag tests", async () => { let p = stateVariables["/P"]; - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + let x = constantFromAst(p.stateValues.xs[0]); + let y = constantFromAst(p.stateValues.xs[1]); expect(x).greaterThan(0.1 + 1e-12); expect(x).lessThan(0.1 + 1e-3); @@ -1820,8 +1804,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(x).closeTo(4, 1e-12); expect(Math.log(2 * x)).closeTo(y, 1e-5); @@ -1837,8 +1821,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(x).closeTo(6, 1e-12); expect(Math.log(2 * x)).closeTo(y, 1e-5); @@ -1854,8 +1838,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(x).greaterThan(0.1 + 1e-12); expect(x).lessThan(0.1 + 1e-3); @@ -1882,8 +1866,8 @@ describe("Function tag tests", async () => { let p = stateVariables["/P"]; - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + let x = constantFromAst(p.stateValues.xs[0]); + let y = constantFromAst(p.stateValues.xs[1]); expect(x).eq(0.1); expect(Math.log(2 * x)).closeTo(y, 1e-5); @@ -1899,8 +1883,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(x).closeTo(4, 1e-12); expect(Math.log(2 * x)).closeTo(y, 1e-5); @@ -1916,8 +1900,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(x).lessThan(6 - 1e-12); expect(x).greaterThan(6 - 1e-3); @@ -1934,8 +1918,8 @@ describe("Function tag tests", async () => { p = stateVariables["/P"]; - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); expect(x).closeTo(0.1, 1e-12); expect(Math.log(2 * x)).closeTo(y, 1e-5); diff --git a/packages/doenetml-worker/src/test/tagSpecific/substitute.test.ts b/packages/doenetml-worker/src/test/tagSpecific/substitute.test.ts new file mode 100644 index 000000000..6eb52aa26 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/substitute.test.ts @@ -0,0 +1,1586 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { cleanLatex } from "../utils/math"; +import { + updateBooleanInputValue, + updateMathInputValue, + updateMatrixInputValue, + updateTextInputValue, +} from "../utils/actions"; +import me from "math-expressions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Substitute tag tests", async () => { + async function test_sub_alpha_x2(core) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value.tree).eqls([ + "+", + "alpha", + ["^", "b", 2], + ]); + expect(stateVariables["/one"].stateValues.value.tree).eqls([ + "+", + "alpha", + ["^", "b", 2], + ]); + expect(stateVariables["/s_two"].stateValues.value.tree).eqls([ + "+", + "d", + ["^", "b", 2], + ]); + expect(stateVariables["/two"].stateValues.value.tree).eqls([ + "+", + "d", + ["^", "b", 2], + ]); + } + + it("substitute into string sugared to math", async () => { + let core = await createTestCore({ + doenetML: ` + + alpha+x^2 + + + + alpha+x^2 + + + `, + }); + + await test_sub_alpha_x2(core); + }); + + it("substitute into string sugared to math, explicit type", async () => { + let core = await createTestCore({ + doenetML: ` + + alpha+x^2 + + + + alpha+x^2 + + + `, + }); + + await test_sub_alpha_x2(core); + }); + + it("substitute into math", async () => { + let core = await createTestCore({ + doenetML: ` + + alpha+x^2 + + + + alpha+x^2 + + + `, + }); + + await test_sub_alpha_x2(core); + }); + + it("change simplify", async () => { + let core = await createTestCore({ + doenetML: ` + + + x+y + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value.tree).eqls([ + "+", + "y", + "y", + ]); + expect(stateVariables["/one"].stateValues.value.tree).eqls([ + "+", + "y", + "y", + ]); + + // set simplify to full + await updateTextInputValue({ + text: "full", + componentName: "/simplify", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value.tree).eqls([ + "*", + 2, + "y", + ]); + expect(stateVariables["/one"].stateValues.value.tree).eqls([ + "*", + 2, + "y", + ]); + + // set simplify back to none + await updateTextInputValue({ + text: "none", + componentName: "/simplify", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value.tree).eqls([ + "+", + "y", + "y", + ]); + expect(stateVariables["/one"].stateValues.value.tree).eqls([ + "+", + "y", + "y", + ]); + }); + + it("substitute with math, is global substitution", async () => { + let core = await createTestCore({ + doenetML: ` + + + x^2+alpha + x/alpha + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value.tree).eqls([ + "+", + ["^", "b", 2], + "d", + ["/", "b", "d"], + ]); + expect(stateVariables["/one"].stateValues.value.tree).eqls([ + "+", + ["^", "b", 2], + "d", + ["/", "b", "d"], + ]); + }); + + it("dynamically change parameters, in math", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + $original + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value.tree).eqls([ + "+", + "y", + ["^", "b", 2], + ]); + expect(stateVariables["/one"].stateValues.value.tree).eqls([ + "+", + "y", + ["^", "b", 2], + ]); + + // change original + await updateMathInputValue({ + latex: "q/x", + componentName: "/original", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value.tree).eqls([ + "/", + "q", + "b", + ]); + expect(stateVariables["/one"].stateValues.value.tree).eqls([ + "/", + "q", + "b", + ]); + + // change match so does not match + await updateMathInputValue({ + latex: "c", + componentName: "/match", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value.tree).eqls([ + "/", + "q", + "x", + ]); + expect(stateVariables["/one"].stateValues.value.tree).eqls([ + "/", + "q", + "x", + ]); + + // change match so matches again + await updateMathInputValue({ + latex: "q", + componentName: "/match", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value.tree).eqls([ + "/", + "b", + "x", + ]); + expect(stateVariables["/one"].stateValues.value.tree).eqls([ + "/", + "b", + "x", + ]); + + // change replacement + await updateMathInputValue({ + latex: "m^2", + componentName: "/replacement", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value.tree).eqls([ + "/", + ["^", "m", 2], + "x", + ]); + expect(stateVariables["/one"].stateValues.value.tree).eqls([ + "/", + ["^", "m", 2], + "x", + ]); + }); + + // Is the desired behavior? It is how substitute works in math-expressinons. + it("substitute does not change numbers in math", async () => { + let core = await createTestCore({ + doenetML: ` + + x+1 + + + x+1 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/one"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/s_two"].stateValues.value.tree).eqls([ + "+", + "y", + 1, + ]); + expect(stateVariables["/two"].stateValues.value.tree).eqls([ + "+", + "y", + 1, + ]); + }); + + it("substitute into string sugared to text", async () => { + let core = await createTestCore({ + doenetML: ` + + Big banana BerAtes brown bErry. + + + + Big banana BerAtes brown bErry. + + + `, + }); + + let s1 = "Big banana cHerAtes brown cHerry."; + let s2 = "Big banana chideSbrown cHerry."; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value.trim()).eq(s1); + expect(stateVariables["/one"].stateValues.value.trim()).eq(s1); + expect(stateVariables["/s_two"].stateValues.value.trim()).eq(s2); + expect(stateVariables["/two"].stateValues.value.trim()).eq(s2); + }); + + it("substitute into text", async () => { + let core = await createTestCore({ + doenetML: ` + + Big banana BerAtes brown bErry. + + + + Big banana BerAtes brown bErry. + + + `, + }); + + let s1 = "Big banana cHerAtes brown cHerry."; + let s2 = "Big banana chideSbrown cHerry."; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value).eq(s1); + expect(stateVariables["/one"].stateValues.value).eq(s1); + expect(stateVariables["/s_two"].stateValues.value).eq(s2); + expect(stateVariables["/two"].stateValues.value).eq(s2); + }); + + it("substitute into text, match case", async () => { + let core = await createTestCore({ + doenetML: ` + + Big banana BerAtes brown bErry. + + + Big banana BerAtes brown bErry. + + `, + }); + + let s1 = "Big banana cHerAtes brown bErry."; + let s2 = "Big banana BerAtes brown cHerry."; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value).eq(s1); + expect(stateVariables["/one"].stateValues.value).eq(s1); + expect(stateVariables["/s_two"].stateValues.value).eq(s2); + expect(stateVariables["/two"].stateValues.value).eq(s2); + }); + + it("substitute into text, preserve case", async () => { + let core = await createTestCore({ + doenetML: ` + + A word WORD Word wOrD WoRd. + + + A word WORD Word wOrD WoRd. + + + A word WORD Word wOrD WoRd. + + `, + }); + + let s1 = "A new NEW New new New."; + let s2 = "A new NEW NEW nEW NEW."; + let s3 = "A new NEW NeW neW NeW."; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value).eq(s1); + expect(stateVariables["/one"].stateValues.value).eq(s1); + expect(stateVariables["/s_two"].stateValues.value).eq(s2); + expect(stateVariables["/two"].stateValues.value).eq(s2); + expect(stateVariables["/s_three"].stateValues.value).eq(s3); + expect(stateVariables["/three"].stateValues.value).eq(s3); + }); + + it("substitute into text, match whole word", async () => { + let core = await createTestCore({ + doenetML: ` + + Big banana BerAtes brown bErry. + + + Big banana BerAtes brown bErry. + + `, + }); + + let s1 = "Big banana BerAtes brown bErry."; + let s2 = "Big banana chideS brown bErry."; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value).eq(s1); + expect(stateVariables["/one"].stateValues.value).eq(s1); + expect(stateVariables["/s_two"].stateValues.value).eq(s2); + expect(stateVariables["/two"].stateValues.value).eq(s2); + }); + + it("substitute into text, match whole word with spaces", async () => { + let core = await createTestCore({ + doenetML: ` + + Big banana BerAtes brown bErry. + + + Big banana BerAtes brown bErry. + + `, + }); + + let s1 = "Big banana BerAtes brown bErry."; + let s2 = "Big bananachideSbrown bErry."; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value).eq(s1); + expect(stateVariables["/one"].stateValues.value).eq(s1); + expect(stateVariables["/s_two"].stateValues.value).eq(s2); + expect(stateVariables["/two"].stateValues.value).eq(s2); + }); + + it("substitute into text, is global substitution", async () => { + let core = await createTestCore({ + doenetML: ` + a + + Big babana BerAtes brown bErry. + + `, + }); + + let s1 = "cig cacana cerAtes crown cErry."; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value).eq(s1); + expect(stateVariables["/one"].stateValues.value).eq(s1); + }); + + it("change pattern and replaces in text", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + $original + + + `, + }); + + let s1 = "Big banana cHerAtes brown cHerry."; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value).eq(s1); + expect(stateVariables["/one"].stateValues.value).eq(s1); + + // change original + await updateTextInputValue({ + text: "The bicycle belongs to me.", + componentName: "/original", + core, + }); + let s2 = "The bicycle cHelongs to me."; + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value).eq(s2); + expect(stateVariables["/one"].stateValues.value).eq(s2); + + // change match so does not match + await updateTextInputValue({ + text: "bike", + componentName: "/match", + core, + }); + let s3 = "The bicycle belongs to me."; + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value).eq(s3); + expect(stateVariables["/one"].stateValues.value).eq(s3); + + // change match so matches again + await updateTextInputValue({ + text: "e b", + componentName: "/match", + core, + }); + let s4 = "ThcHeicyclcHeelongs to me."; + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value).eq(s4); + expect(stateVariables["/one"].stateValues.value).eq(s4); + + // change match and replacement + await updateTextInputValue({ + text: "bicycle", + componentName: "/match", + core, + }); + await updateTextInputValue({ + text: "scooter", + componentName: "/replacement", + core, + }); + let s5 = "The scooter belongs to me."; + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s_one"].stateValues.value).eq(s5); + expect(stateVariables["/one"].stateValues.value).eq(s5); + }); + + it("modify in inverse direction, math", async () => { + let core = await createTestCore({ + doenetML: ` +

Original:

+

Original 2:$orig

+ +

Match:

+

Replacement:

+ +

Substituted: $orig2

+ +

Substituted 2:

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let origExpr = me.fromText("x^2+2x+3y").tree; + let subbedExpr = me.fromText("b^2+2b+3y").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // change original + await updateMathInputValue({ + latex: "x^2+2x+3x", + componentName: "/orig", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("x^2+2x+3x").tree; + subbedExpr = me.fromText("b^2+2b+3b").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // change subbed + await updateMathInputValue({ + latex: "b^2+2b+3v/b", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("x^2+2x+3v/x").tree; + subbedExpr = me.fromText("b^2+2b+3v/b").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // change replacement so that it is in original + await updateMathInputValue({ + latex: "v", + componentName: "/replacement", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("x^2+2x+3v/x").tree; + subbedExpr = me.fromText("v^2+2v+3v/v").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // Cannot modify subbed + await updateMathInputValue({ + latex: "v^2+2v+3v/(v+1)", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("x^2+2x+3v/x").tree; + subbedExpr = me.fromText("v^2+2v+3v/v").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // change original to not contain replacement + await updateMathInputValue({ + latex: "x^2+2x+3u/x", + componentName: "/orig", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("x^2+2x+3u/x").tree; + subbedExpr = me.fromText("v^2+2v+3u/v").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // Can modify subbed again + await updateMathInputValue({ + latex: "v^5+2v+3u/v", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("x^5+2x+3u/x").tree; + subbedExpr = me.fromText("v^5+2v+3u/v").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // change replacement to be more than a variable + await updateMathInputValue({ + latex: "v+1", + componentName: "/replacement", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("x^5+2x+3u/x").tree; + subbedExpr = me.fromText("(v+1)^5+2(v+1)+3u/(v+1)").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // Cannot modify subbed + await updateMathInputValue({ + latex: "+7(v+1)^5+2(v+1)+3u/(v+1)", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("x^5+2x+3u/x").tree; + subbedExpr = me.fromText("(v+1)^5+2(v+1)+3u/(v+1)").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // change replacement to involve a subscript + await updateMathInputValue({ + latex: "v_3", + componentName: "/replacement", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("x^5+2x+3u/x").tree; + subbedExpr = me.fromText("v_3^5+2v_3+3u/v_3").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // Can modify subbed once more + await updateMathInputValue({ + latex: "v_9^5+2v_3+3u/v_3", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("v_9^5+2x+3u/x").tree; + subbedExpr = me.fromText("v_9^5+2v_3+3u/v_3").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // change match to involve a subscript + await updateMathInputValue({ + latex: "v_9", + componentName: "/match", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("v_9^5+2x+3u/x").tree; + subbedExpr = me.fromText("v_3^5+2x+3u/x").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // Can still modify subbed + await updateMathInputValue({ + latex: "v_3^5+2x+3u/v_3", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("v_9^5+2x+3u/v_9").tree; + subbedExpr = me.fromText("v_3^5+2x+3u/v_3").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + + // Cannot modify subbed to include match + await updateMathInputValue({ + latex: "v_3^5+2x+3u/v_3+v_9", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + origExpr = me.fromText("v_9^5+2x+3u/v_9").tree; + subbedExpr = me.fromText("v_3^5+2x+3u/v_3").tree; + expect(stateVariables["/orig"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/orig2"].stateValues.value.tree).eqls(origExpr); + expect(stateVariables["/subbed"].stateValues.value.tree).eqls( + subbedExpr, + ); + expect(stateVariables["/subbed2"].stateValues.value.tree).eqls( + subbedExpr, + ); + }); + + it("modify in inverse direction, text", async () => { + let core = await createTestCore({ + doenetML: ` +

Original:

+

Original 2:$orig

+ +

Match:

+

Match whole word:

+

Match case:

+

Replacement:

+

Preserve case:

+ +

Substituted: $orig2

+ +

Substituted 2:

+ +

$matchCase.value{assignNames="matchCase2"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq("hello there"); + expect(stateVariables["/orig2"].stateValues.value).eq("hello there"); + expect(stateVariables["/subbed"].stateValues.value).eq("bye there"); + expect(stateVariables["/subbed2"].stateValues.value).eq("bye there"); + + // change original + await updateTextInputValue({ + text: "hello thereHello", + componentName: "/orig", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello thereHello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello thereHello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq("bye therebye"); + expect(stateVariables["/subbed2"].stateValues.value).eq("bye therebye"); + + // change subbed + await updateTextInputValue({ + text: "bye therebyeBye", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello therehellohello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello therehellohello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "bye therebyebye", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "bye therebyebye", + ); + + // change replacement so that it is in original + await updateTextInputValue({ + text: "There", + componentName: "/replacement", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello therehellohello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello therehellohello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "There thereThereThere", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "There thereThereThere", + ); + + // Cannot modify subbed + await updateTextInputValue({ + text: "There thereThereThere extra", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello therehellohello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello therehellohello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "There thereThereThere", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "There thereThereThere", + ); + + // change original to not contain replacement + await updateTextInputValue({ + text: "hello thenhellohello", + componentName: "/orig", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello thenhellohello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello thenhellohello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "There thenThereThere", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "There thenThereThere", + ); + + // Can modify subbed again + await updateTextInputValue({ + text: "There thenThereThe", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello thenhelloThe", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello thenhelloThe", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "There thenThereThe", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "There thenThereThe", + ); + + // Cannot modify subbed to include match + await updateTextInputValue({ + text: "There thenThereTheHELLO", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello thenhelloThe", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello thenhelloThe", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "There thenThereThe", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "There thenThereThe", + ); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/wholeWord", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello thenhelloThe", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello thenhelloThe", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "There thenhelloThe", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "There thenhelloThe", + ); + + //change replacement so matches original, but not as a whole word + await updateTextInputValue({ + text: "Then", + componentName: "/replacement", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello thenhelloThe", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello thenhelloThe", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Then thenhelloThe", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Then thenhelloThe", + ); + + // Can still modify subbed + await updateTextInputValue({ + text: "Then thenhelloThere", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello thenhelloThere", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello thenhelloThere", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Then thenhelloThere", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Then thenhelloThere", + ); + + // Cannot modify subbed by adding spaces to separate match + await updateTextInputValue({ + text: "Then then hello There", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello thenhelloThere", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello thenhelloThere", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Then thenhelloThere", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Then thenhelloThere", + ); + + // change original so that replacement matches original as a whole word + await updateTextInputValue({ + text: "hello then helloThere", + componentName: "/orig", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello then helloThere", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello then helloThere", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Then then helloThere", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Then then helloThere", + ); + + // Cannot modify subbed due to replacement match + await updateTextInputValue({ + text: "Then then helloTherenothing", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello then helloThere", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello then helloThere", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Then then helloThere", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Then then helloThere", + ); + + // match case + await updateBooleanInputValue({ + boolean: true, + componentName: "/matchCase", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello then helloThere", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello then helloThere", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Then then helloThere", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Then then helloThere", + ); + + // Now can modify subbed due to replacement not matching original case + await updateTextInputValue({ + text: "Then then helloThere Hello", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello then helloThere Hello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello then helloThere Hello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Then then helloThere Hello", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Then then helloThere Hello", + ); + + // Cannot add match to subbed + await updateTextInputValue({ + text: "Then then helloThere Hello hello", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "hello then helloThere Hello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "hello then helloThere Hello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Then then helloThere Hello", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Then then helloThere Hello", + ); + + // Change subbed to switch cases + await updateTextInputValue({ + text: "then Then helloThere Hello", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "then hello helloThere Hello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "then hello helloThere Hello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "then Then helloThere Hello", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "then Then helloThere Hello", + ); + + // preserve case + await updateBooleanInputValue({ + boolean: true, + componentName: "/preserveCase", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "then hello helloThere Hello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "then hello helloThere Hello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "then then helloThere Hello", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "then then helloThere Hello", + ); + + // Cannot change subbed since original contains effective replacement + await updateTextInputValue({ + text: "then Then helloThere Hello more", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "then hello helloThere Hello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "then hello helloThere Hello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "then then helloThere Hello", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "then then helloThere Hello", + ); + + // change case of match so that effective replacement is not in original + await updateTextInputValue({ + text: "Hello", + componentName: "/match", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "then hello helloThere Hello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "then hello helloThere Hello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "then hello helloThere Then", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "then hello helloThere Then", + ); + + // Can now change subbed + await updateTextInputValue({ + text: "Then HELLO THEN helloThere Then", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "Hello HELLO THEN helloThere Hello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "Hello HELLO THEN helloThere Hello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Then HELLO THEN helloThere Then", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Then HELLO THEN helloThere Then", + ); + + // change case of match so that effective replacement is again in original + await updateTextInputValue({ + text: "HELLO", + componentName: "/match", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "Hello HELLO THEN helloThere Hello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "Hello HELLO THEN helloThere Hello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Hello THEN THEN helloThere Hello", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Hello THEN THEN helloThere Hello", + ); + + // Cannot change subbed + await updateTextInputValue({ + text: "Hello THEN THEN helloThere Hello ineffective", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "Hello HELLO THEN helloThere Hello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "Hello HELLO THEN helloThere Hello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Hello THEN THEN helloThere Hello", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Hello THEN THEN helloThere Hello", + ); + + // change original so no longer has effective replacement + await updateTextInputValue({ + text: "Hello HELLO Then helloThere Hello", + componentName: "/orig", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "Hello HELLO Then helloThere Hello", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "Hello HELLO Then helloThere Hello", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Hello THEN Then helloThere Hello", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Hello THEN Then helloThere Hello", + ); + + // Can change subbed once more + await updateTextInputValue({ + text: "Hello THEN Then helloThere THEN", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "Hello HELLO Then helloThere HELLO", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "Hello HELLO Then helloThere HELLO", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Hello THEN Then helloThere THEN", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Hello THEN Then helloThere THEN", + ); + + // Cannot add match to subbed + await updateTextInputValue({ + text: "Hello THEN Then helloThere THEN HELLO", + componentName: "/subbed2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].stateValues.value).eq( + "Hello HELLO Then helloThere HELLO", + ); + expect(stateVariables["/orig2"].stateValues.value).eq( + "Hello HELLO Then helloThere HELLO", + ); + expect(stateVariables["/subbed"].stateValues.value).eq( + "Hello THEN Then helloThere THEN", + ); + expect(stateVariables["/subbed2"].stateValues.value).eq( + "Hello THEN Then helloThere THEN", + ); + }); + + it("substitute with incomplete attributes does nothing", async () => { + let core = await createTestCore({ + doenetML: ` + x+1 + x+1 + x+1 + hello + hello + hello + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + + expect(stateVariables["/t1"].stateValues.value).eq("hello"); + expect(stateVariables["/t2"].stateValues.value).eq("hello"); + expect(stateVariables["/t3"].stateValues.value).eq("hello"); + }); + + it("rounding with math", async () => { + let core = await createTestCore({ + doenetML: ` + ax+847.29418392+5y + ax+847.29418392+5y + ax+847.29418392+5y + ax+847.29418392+5y + +

+ $orig + + + $orig + + + $orig + + + $orig +

+

+ + +

+ + +

+ $origDig3 + + + $origDig3 + + + $origDig3 + + + $origDig3 +

+

+ + +

+ +

+ $origDec3 + + + $origDec3 + + + $origDec3 + + + $origDec3 +

+

+ + +

+ +

+ $origPad + + + $origPad + + + $origPad + + + $origPad +

+

+ + +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/e1"]); + + expect(cleanLatex(stateVariables["/e1"].stateValues.latex)).eq( + "0.0739x+847.29+5y", + ); + expect(cleanLatex(stateVariables["/e1Dig4"].stateValues.latex)).eq( + "0.07395x+847.3+5y", + ); + expect(cleanLatex(stateVariables["/e1Dec4"].stateValues.latex)).eq( + "0.0739x+847.2942+5y", + ); + expect(cleanLatex(stateVariables["/e1Pad"].stateValues.latex)).eq( + "0.0739x+847.29+5.00y", + ); + expect(cleanLatex(stateVariables["/e1Dig4a"].stateValues.latex)).eq( + "0.07395x+847.3+5y", + ); + expect(cleanLatex(stateVariables["/e1Dec4a"].stateValues.latex)).eq( + "0.0739x+847.2942+5y", + ); + expect(cleanLatex(stateVariables["/e2"].stateValues.latex)).eq( + "0.0739x+847+5y", + ); + expect(cleanLatex(stateVariables["/e2Dig4"].stateValues.latex)).eq( + "0.07395x+847.3+5y", + ); + expect(cleanLatex(stateVariables["/e2Dec4"].stateValues.latex)).eq( + "0.0739x+847.2942+5y", + ); + expect(cleanLatex(stateVariables["/e2Pad"].stateValues.latex)).eq( + "0.0739x+847+5.00y", + ); + expect(cleanLatex(stateVariables["/e2Dig4a"].stateValues.latex)).eq( + "0.07395x+847.3+5y", + ); + expect(cleanLatex(stateVariables["/e2Dec4a"].stateValues.latex)).eq( + "0.0739x+847.2942+5y", + ); + expect(cleanLatex(stateVariables["/e3"].stateValues.latex)).eq( + "0.074x+847.294+5y", + ); + expect(cleanLatex(stateVariables["/e3Dig4"].stateValues.latex)).eq( + "0.07395x+847.3+5y", + ); + expect(cleanLatex(stateVariables["/e3Dec4"].stateValues.latex)).eq( + "0.0739x+847.2942+5y", + ); + expect(cleanLatex(stateVariables["/e3Pad"].stateValues.latex)).eq( + "0.074x+847.294+5.000y", + ); + expect(cleanLatex(stateVariables["/e3Dig4a"].stateValues.latex)).eq( + "0.07395x+847.3+5y", + ); + expect(cleanLatex(stateVariables["/e3Dec4a"].stateValues.latex)).eq( + "0.0739x+847.2942+5y", + ); + expect(cleanLatex(stateVariables["/e4"].stateValues.latex)).eq( + "0.0739x+847.29+5.00y", + ); + expect(cleanLatex(stateVariables["/e4Dig4"].stateValues.latex)).eq( + "0.07395x+847.3+5.000y", + ); + expect(cleanLatex(stateVariables["/e4Dec4"].stateValues.latex)).eq( + "0.0739x+847.2942+5.0000y", + ); + expect(cleanLatex(stateVariables["/e4NoPad"].stateValues.latex)).eq( + "0.0739x+847.29+5y", + ); + expect(cleanLatex(stateVariables["/e4Dig4a"].stateValues.latex)).eq( + "0.07395x+847.3+5.000y", + ); + expect(cleanLatex(stateVariables["/e4Dec4a"].stateValues.latex)).eq( + "0.0739x+847.2942+5.0000y", + ); + }); +}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/substitute.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/substitute.cy.js deleted file mode 100644 index 64254ffb1..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/substitute.cy.js +++ /dev/null @@ -1,2853 +0,0 @@ -import me from "math-expressions"; -import { cesc } from "@doenet/utils"; - -describe("Substitute Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("substitute into string sugared to math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - alpha+x^2 - - - - alpha+x^2 - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("α+b2"); - }); - cy.get(cesc("#\\/two") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d+b2"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "+", - "alpha", - ["^", "b", 2], - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "+", - "alpha", - ["^", "b", 2], - ]); - expect(stateVariables["/s_two"].stateValues.value).eqls([ - "+", - "d", - ["^", "b", 2], - ]); - expect(stateVariables["/two"].stateValues.value).eqls([ - "+", - "d", - ["^", "b", 2], - ]); - }); - }); - - it("substitute into string sugared to math, explicit type", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - alpha+x^2 - - - - alpha+x^2 - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("α+b2"); - }); - cy.get(cesc("#\\/two") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d+b2"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "+", - "alpha", - ["^", "b", 2], - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "+", - "alpha", - ["^", "b", 2], - ]); - expect(stateVariables["/s_two"].stateValues.value).eqls([ - "+", - "d", - ["^", "b", 2], - ]); - expect(stateVariables["/two"].stateValues.value).eqls([ - "+", - "d", - ["^", "b", 2], - ]); - }); - }); - - it("substitute into math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - alpha+x^2 - - - - alpha+x^2 - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("α+b2"); - }); - cy.get(cesc("#\\/two") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d+b2"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "+", - "alpha", - ["^", "b", 2], - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "+", - "alpha", - ["^", "b", 2], - ]); - expect(stateVariables["/s_two"].stateValues.value).eqls([ - "+", - "d", - ["^", "b", 2], - ]); - expect(stateVariables["/two"].stateValues.value).eqls([ - "+", - "d", - ["^", "b", 2], - ]); - }); - }); - - it("change simplify", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - x+y - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "+", - "y", - "y", - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "+", - "y", - "y", - ]); - }); - - cy.log("set simplify to full"); - cy.get(cesc("#\\/simplify_input")).clear().type("full{enter}"); - - cy.get(cesc("#\\/one") + " .mjx-mrow").should("contain.text", "2y"); - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "*", - 2, - "y", - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "*", - 2, - "y", - ]); - }); - - cy.log("set simplify back to none"); - cy.get(cesc("#\\/simplify_input")).clear().type("none{enter}"); - - cy.get(cesc("#\\/one") + " .mjx-mrow").should("contain.text", "y+y"); - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "+", - "y", - "y", - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "+", - "y", - "y", - ]); - }); - }); - - it("substitute with math, global", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - x^2+alpha + x/alpha - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b2+d+bd"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "+", - ["^", "b", 2], - "d", - ["/", "b", "d"], - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "+", - ["^", "b", 2], - "d", - ["/", "b", "d"], - ]); - }); - }); - - it("change values in math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - $original - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+b2"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "+", - "y", - ["^", "b", 2], - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "+", - "y", - ["^", "b", 2], - ]); - }); - - cy.log("change original"); - cy.get(cesc("#\\/original") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}q/x{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/one") + " .mjx-mrow").should("contain.text", "qb"); - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qb"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "/", - "q", - "b", - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "/", - "q", - "b", - ]); - }); - - cy.log("change match so does not match"); - cy.get(cesc("#\\/match") + " textarea").type( - `{end}{backspace}{backspace}c{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/one") + " .mjx-mrow").should("contain.text", "qx"); - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qx"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "/", - "q", - "x", - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "/", - "q", - "x", - ]); - }); - - cy.log("change match so matches again"); - cy.get(cesc("#\\/match") + " textarea").type( - `{end}{backspace}{backspace}q{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/one") + " .mjx-mrow").should("contain.text", "bx"); - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("bx"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "/", - "b", - "x", - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "/", - "b", - "x", - ]); - }); - - cy.log("change replacement"); - cy.get(cesc("#\\/replacement") + " textarea").type( - `{end}{backspace}{backspace}m^2{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/one") + " .mjx-mrow").should("contain.text", "m2x"); - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("m2x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "/", - ["^", "m", 2], - "x", - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "/", - ["^", "m", 2], - "x", - ]); - }); - }); - - // Is the desired behavior? It is how substitute works in math-expressinons. - it("substitute does not change numbers in math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - x+1 - - - x+1 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/one") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc("#\\/two") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect(stateVariables["/one"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect(stateVariables["/s_two"].stateValues.value).eqls([ - "+", - "y", - 1, - ]); - expect(stateVariables["/two"].stateValues.value).eqls([ - "+", - "y", - 1, - ]); - }); - }); - - it("substitute into string sugared to text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - Big banana BerAtes brown bErry. - - - - Big banana BerAtes brown bErry. - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let s1 = "Big banana cHerAtes brown cHerry."; - let s2 = "Big banana chideSbrown cHerry."; - - cy.get(cesc("#\\/one")).should("contain.text", s1); - cy.get(cesc("#\\/two")).should("contain.text", s2); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value.trim()).eq(s1); - expect(stateVariables["/one"].stateValues.value.trim()).eq(s1); - expect(stateVariables["/s_two"].stateValues.value.trim()).eq(s2); - expect(stateVariables["/two"].stateValues.value.trim()).eq(s2); - }); - }); - - it("substitute into text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - Big banana BerAtes brown bErry. - - - - Big banana BerAtes brown bErry. - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let s1 = "Big banana cHerAtes brown cHerry."; - let s2 = "Big banana chideSbrown cHerry."; - - cy.get(cesc("#\\/one")).should("have.text", s1); - cy.get(cesc("#\\/two")).should("have.text", s2); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eq(s1); - expect(stateVariables["/one"].stateValues.value).eq(s1); - expect(stateVariables["/s_two"].stateValues.value).eq(s2); - expect(stateVariables["/two"].stateValues.value).eq(s2); - }); - }); - - it("substitute into text, match case", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - Big banana BerAtes brown bErry. - - - Big banana BerAtes brown bErry. - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let s1 = "Big banana cHerAtes brown bErry."; - let s2 = "Big banana BerAtes brown cHerry."; - - cy.get(cesc("#\\/one")).should("have.text", s1); - cy.get(cesc("#\\/two")).should("have.text", s2); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eq(s1); - expect(stateVariables["/one"].stateValues.value).eq(s1); - expect(stateVariables["/s_two"].stateValues.value).eq(s2); - expect(stateVariables["/two"].stateValues.value).eq(s2); - }); - }); - - it("substitute into text, preserve case", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - A word WORD Word wOrD WoRd. - - - A word WORD Word wOrD WoRd. - - - A word WORD Word wOrD WoRd. - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let s1 = "A new NEW New new New."; - let s2 = "A new NEW NEW nEW NEW."; - let s3 = "A new NEW NeW neW NeW."; - - cy.get(cesc("#\\/one")).should("have.text", s1); - cy.get(cesc("#\\/two")).should("have.text", s2); - cy.get(cesc("#\\/three")).should("have.text", s3); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eq(s1); - expect(stateVariables["/one"].stateValues.value).eq(s1); - expect(stateVariables["/s_two"].stateValues.value).eq(s2); - expect(stateVariables["/two"].stateValues.value).eq(s2); - expect(stateVariables["/s_three"].stateValues.value).eq(s3); - expect(stateVariables["/three"].stateValues.value).eq(s3); - }); - }); - - it("substitute into text, match whole word", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - Big banana BerAtes brown bErry. - - - Big banana BerAtes brown bErry. - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let s1 = "Big banana BerAtes brown bErry."; - let s2 = "Big banana chideS brown bErry."; - - cy.get(cesc("#\\/one")).should("have.text", s1); - cy.get(cesc("#\\/two")).should("have.text", s2); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eq(s1); - expect(stateVariables["/one"].stateValues.value).eq(s1); - expect(stateVariables["/s_two"].stateValues.value).eq(s2); - expect(stateVariables["/two"].stateValues.value).eq(s2); - }); - }); - - it("substitute into text, match whole word with spaces", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - Big banana BerAtes brown bErry. - - - Big banana BerAtes brown bErry. - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let s1 = "Big banana BerAtes brown bErry."; - let s2 = "Big bananachideSbrown bErry."; - - cy.get(cesc("#\\/one")).should("have.text", s1); - cy.get(cesc("#\\/two")).should("have.text", s2); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eq(s1); - expect(stateVariables["/one"].stateValues.value).eq(s1); - expect(stateVariables["/s_two"].stateValues.value).eq(s2); - expect(stateVariables["/two"].stateValues.value).eq(s2); - }); - }); - - it("substitute into text, global", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - Big babana BerAtes brown bErry. - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let s1 = "cig cacana cerAtes crown cErry."; - - cy.get(cesc("#\\/one")).should("have.text", s1); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eq(s1); - expect(stateVariables["/one"].stateValues.value).eq(s1); - }); - }); - - it("change pattern and replaces in text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - $original - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let s1 = "Big banana cHerAtes brown cHerry."; - - cy.get(cesc("#\\/one")).should("have.text", s1); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eq(s1); - expect(stateVariables["/one"].stateValues.value).eq(s1); - }); - - cy.log("change original"); - cy.get(cesc("#\\/original_input")) - .clear() - .type(`The bicycle belongs to me.{enter}`); - let s2 = "The bicycle cHelongs to me."; - cy.get(cesc("#\\/one")).should("have.text", s2); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eq(s2); - expect(stateVariables["/one"].stateValues.value).eq(s2); - }); - - cy.log("change match so does not match"); - cy.get(cesc("#\\/match_input")).clear().type(`bike{enter}`); - let s3 = "The bicycle belongs to me."; - cy.get(cesc("#\\/one")).should("have.text", s3); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eq(s3); - expect(stateVariables["/one"].stateValues.value).eq(s3); - }); - - cy.log("change match so matches again"); - cy.get(cesc("#\\/match_input")).clear().type(`e b{enter}`); - let s4 = "ThcHeicyclcHeelongs to me."; - cy.get(cesc("#\\/one")).should("have.text", s4); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eq(s4); - expect(stateVariables["/one"].stateValues.value).eq(s4); - }); - - cy.log("change match and replacement"); - cy.get(cesc("#\\/match_input")).clear().type(`bicycle{enter}`); - cy.get(cesc("#\\/replacement_input")).clear().type(`scooter{enter}`); - let s5 = "The scooter belongs to me."; - cy.get(cesc("#\\/one")).should("have.text", s5); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/s_one"].stateValues.value).eq(s5); - expect(stateVariables["/one"].stateValues.value).eq(s5); - }); - }); - - it("modify in inverse direction, math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Original:

-

Original 2:$orig

- -

Match:

-

Replacement:

- -

Substituted: $orig2

- -

Substituted 2:

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x2+2x+3y", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2+2x+3y"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b2+2b+3y"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "b2+2b+3y", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("x^2+2x+3y").tree; - let subbedExpr = me.fromText("b^2+2b+3y").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("change original"); - cy.get(cesc("#\\/orig") + " textarea").type( - `{end}{backspace}x{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/orig2") + " .mjx-mrow").should( - "contain.text", - "x2+2x+3x", - ); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should( - "contain.text", - "b2+2b+3b", - ); - - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x2+2x+3x", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2+2x+3x"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b2+2b+3b"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "b2+2b+3b", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("x^2+2x+3x").tree; - let subbedExpr = me.fromText("b^2+2b+3b").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("change subbed"); - cy.get(cesc("#\\/subbed2") + " textarea").type( - `{end}{backspace}v/b{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/orig2") + " .mjx-mrow").should( - "contain.text", - "x2+2x+3vx", - ); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should( - "contain.text", - "b2+2b+3vb", - ); - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x2+2x+3vx", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2+2x+3vx"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b2+2b+3vb"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "b2+2b+3vb", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("x^2+2x+3v/x").tree; - let subbedExpr = me.fromText("b^2+2b+3v/b").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("change replacement so that it is in original"); - cy.get(cesc("#\\/replacement") + " textarea").type( - `{end}{backspace}v{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow").should( - "contain.text", - "v2+2v+3vv", - ); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should( - "contain.text", - "v2+2v+3vv", - ); - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x2+2x+3vx", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2+2x+3vx"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v2+2v+3vv"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v2+2v+3vv", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("x^2+2x+3v/x").tree; - let subbedExpr = me.fromText("v^2+2v+3v/v").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("Cannot modify subbed"); - cy.get(cesc("#\\/subbed2") + " textarea").type( - `{end}{backspace}+1{enter}`, - { force: true }, - ); - - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should( - "not.contain.text", - "v2+2v+3vv+1", - ); - - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x2+2x+3vx", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2+2x+3vx"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v2+2v+3vv"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v2+2v+3vv", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("x^2+2x+3v/x").tree; - let subbedExpr = me.fromText("v^2+2v+3v/v").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("change original to not contain replacement"); - cy.get(cesc("#\\/orig") + " textarea").type( - `{end}{leftArrow}{leftArrow}{leftArrow}{backspace}u{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/orig2") + " .mjx-mrow").should( - "contain.text", - "x2+2x+3ux", - ); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should( - "contain.text", - "v2+2v+3uv", - ); - - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x2+2x+3ux", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2+2x+3ux"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v2+2v+3uv"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v2+2v+3uv", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("x^2+2x+3u/x").tree; - let subbedExpr = me.fromText("v^2+2v+3u/v").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("Can modify subbed again"); - cy.get(cesc("#\\/subbed2") + " textarea").type( - `{home}{rightArrow}{rightArrow}{rightArrow}{backspace}5{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/orig2") + " .mjx-mrow").should( - "contain.text", - "x5+2x+3ux", - ); - - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x5+2x+3ux", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x5+2x+3ux"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v5+2v+3uv"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v5+2v+3uv", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("x^5+2x+3u/x").tree; - let subbedExpr = me.fromText("v^5+2v+3u/v").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("change replacement to be more than a variable"); - cy.get(cesc("#\\/replacement") + " textarea").type(`{end}+1{enter}`, { - force: true, - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow").should( - "contain.text", - "(v+1)5+2(v+1)+3uv+1", - ); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should( - "contain.text", - "(v+1)5+2(v+1)+3uv+1", - ); - - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x5+2x+3ux", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x5+2x+3ux"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(v+1)5+2(v+1)+3uv+1"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "(v+1)5+2(v+1)+3uv+1", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("x^5+2x+3u/x").tree; - let subbedExpr = me.fromText("(v+1)^5+2(v+1)+3u/(v+1)").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("Cannot modify subbed"); - cy.get(cesc("#\\/subbed2") + " textarea").type(`{home}+7{enter}`, { - force: true, - }); - - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should( - "not.contain.text", - "+7", - ); - - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x5+2x+3ux", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x5+2x+3ux"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(v+1)5+2(v+1)+3uv+1"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "(v+1)5+2(v+1)+3uv+1", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("x^5+2x+3u/x").tree; - let subbedExpr = me.fromText("(v+1)^5+2(v+1)+3u/(v+1)").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("change replacement to involve a subscript"); - cy.get(cesc("#\\/replacement") + " textarea").type( - `{end}{backspace}{backspace}_3{enter}`, - { force: true }, - ); - - cy.waitUntil(() => - cy - .get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then( - (text) => - text.replace(/[\s\u200B-\u200D\uFEFF]/g, "") === - "v53+2v3+3uv3", - ), - ); - - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x5+2x+3ux", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x5+2x+3ux"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v53+2v3+3uv3"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v53+2v3+3uv3", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("x^5+2x+3u/x").tree; - let subbedExpr = me.fromText("v_3^5+2v_3+3u/v_3").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("Can modify subbed once more"); - cy.get(cesc("#\\/subbed2") + " textarea").type( - `{home}{rightArrow}{rightArrow}{rightArrow}{backspace}9{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow").should( - "contain.text", - "v59+2v3+3uv3", - ); - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v59+2x+3ux", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v59+2x+3ux"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v59+2v3+3uv3"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v59+2v3+3uv3", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("v_9^5+2x+3u/x").tree; - let subbedExpr = me.fromText("v_9^5+2v_3+3u/v_3").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("change match to involve a subscript"); - cy.get(cesc("#\\/match") + " textarea").type( - `{end}{backspace}v_9{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow").should( - "contain.text", - "v53+2x+3ux", - ); - - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v59+2x+3ux", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v59+2x+3ux"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v53+2x+3ux"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v53+2x+3ux", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("v_9^5+2x+3u/x").tree; - let subbedExpr = me.fromText("v_3^5+2x+3u/x").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("Can still modify subbed"); - cy.get(cesc("#\\/subbed2") + " textarea").type( - `{end}{leftArrow}{backspace}v_3{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow").should( - "contain.text", - "v53+2x+3uv3", - ); - - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v59+2x+3uv9", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v59+2x+3uv9"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v53+2x+3uv3"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v53+2x+3uv3", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("v_9^5+2x+3u/v_9").tree; - let subbedExpr = me.fromText("v_3^5+2x+3u/v_3").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - - cy.log("Cannot modify subbed to include match"); - cy.get(cesc("#\\/subbed2") + " textarea").type(`{end}+v_9{enter}`, { - force: true, - }); - - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should( - "not.contain.text", - "+v9", - ); - - cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v59+2x+3uv9", - ); - }); - cy.get(cesc("#\\/orig2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v59+2x+3uv9"); - }); - - cy.get(cesc("#\\/subbed") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v53+2x+3uv3"); - }); - cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "v53+2x+3uv3", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let origExpr = me.fromText("v_9^5+2x+3u/v_9").tree; - let subbedExpr = me.fromText("v_3^5+2x+3u/v_3").tree; - expect(stateVariables["/orig"].stateValues.value).eqls(origExpr); - expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr); - expect(stateVariables["/subbed"].stateValues.value).eqls( - subbedExpr, - ); - expect(stateVariables["/subbed2"].stateValues.value).eqls( - subbedExpr, - ); - }); - }); - - it("modify in inverse direction, text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Original:

-

Original 2:$orig

- -

Match:

-

Match whole word:

-

Match case:

-

Replacement:

-

Preserve case:

- -

Substituted: $orig2

- -

Substituted 2:

- -

$matchCase.value{assignNames="matchCase2"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/orig_input")).should("have.value", "hello there"); - cy.get(cesc("#\\/orig2")).should("have.text", "hello there"); - cy.get(cesc("#\\/subbed")).should("have.text", "bye there"); - cy.get(cesc("#\\/subbed2_input")).should("have.value", "bye there"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq("hello there"); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello there", - ); - expect(stateVariables["/subbed"].stateValues.value).eq("bye there"); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "bye there", - ); - }); - - cy.log("change original"); - cy.get(cesc("#\\/orig_input")).type(`{end}Hello{enter}`); - - cy.get(cesc("#\\/orig2")).should("have.text", "hello thereHello"); - cy.get(cesc("#\\/orig_input")).should("have.value", "hello thereHello"); - cy.get(cesc("#\\/subbed")).should("have.text", "bye therebye"); - cy.get(cesc("#\\/subbed2_input")).should("have.value", "bye therebye"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello thereHello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello thereHello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "bye therebye", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "bye therebye", - ); - }); - - cy.log("change subbed"); - cy.get(cesc("#\\/subbed2_input")).type(`{end}Bye{enter}`); - - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello therehellohello", - ); - cy.get(cesc("#\\/orig2")).should("have.text", "hello therehellohello"); - cy.get(cesc("#\\/subbed")).should("have.text", "bye therebyebye"); - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "bye therebyebye", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello therehellohello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello therehellohello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "bye therebyebye", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "bye therebyebye", - ); - }); - - cy.log("change replacement so that it is in original"); - cy.get(cesc("#\\/replacement_input")).clear().type(`There{enter}`); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "There thereThereThere", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello therehellohello", - ); - cy.get(cesc("#\\/orig2")).should("have.text", "hello therehellohello"); - cy.get(cesc("#\\/subbed")).should("have.text", "There thereThereThere"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello therehellohello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello therehellohello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "There thereThereThere", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "There thereThereThere", - ); - }); - - cy.log("Cannot modify subbed"); - cy.get(cesc("#\\/subbed2_input")).type(`{end} extra{enter}`); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "There thereThereThere", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello therehellohello", - ); - cy.get(cesc("#\\/orig2")).should("have.text", "hello therehellohello"); - cy.get(cesc("#\\/subbed")).should("have.text", "There thereThereThere"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello therehellohello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello therehellohello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "There thereThereThere", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "There thereThereThere", - ); - }); - - cy.log("change original to not contain replacement"); - cy.get(cesc("#\\/orig_input")).type( - "{end}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{backspace}{backspace}n{enter}", - ); - - cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhellohello"); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello thenhellohello", - ); - cy.get(cesc("#\\/subbed")).should("have.text", "There thenThereThere"); - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "There thenThereThere", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello thenhellohello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello thenhellohello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "There thenThereThere", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "There thenThereThere", - ); - }); - - cy.log("Can modify subbed again"); - cy.get(cesc("#\\/subbed2_input")).type( - `{end}{backspace}{backspace}{enter}`, - ); - - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello thenhelloThe", - ); - cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhelloThe"); - cy.get(cesc("#\\/subbed")).should("have.text", "There thenThereThe"); - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "There thenThereThe", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello thenhelloThe", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello thenhelloThe", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "There thenThereThe", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "There thenThereThe", - ); - }); - - cy.log("Cannot modify subbed to include match"); - cy.get(cesc("#\\/subbed2_input")).type(`{end}HELLO{enter}`); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "There thenThereThe", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello thenhelloThe", - ); - cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhelloThe"); - cy.get(cesc("#\\/subbed")).should("have.text", "There thenThereThe"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello thenhelloThe", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello thenhelloThe", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "There thenThereThe", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "There thenThereThe", - ); - }); - - cy.log("match whole word"); - cy.get(cesc("#\\/wholeWord")).click(); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "There thenhelloThe", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello thenhelloThe", - ); - cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhelloThe"); - cy.get(cesc("#\\/subbed")).should("have.text", "There thenhelloThe"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello thenhelloThe", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello thenhelloThe", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "There thenhelloThe", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "There thenhelloThe", - ); - }); - - cy.log( - "change replacement so matches original, but not as a whole word", - ); - cy.get(cesc("#\\/replacement_input")).clear().type(`Then{enter}`); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Then thenhelloThe", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello thenhelloThe", - ); - cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhelloThe"); - cy.get(cesc("#\\/subbed")).should("have.text", "Then thenhelloThe"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello thenhelloThe", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello thenhelloThe", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Then thenhelloThe", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Then thenhelloThe", - ); - }); - - cy.log("Can still modify subbed"); - cy.get(cesc("#\\/subbed2_input")).type(`{end}re{enter}`); - - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello thenhelloThere", - ); - cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhelloThere"); - cy.get(cesc("#\\/subbed")).should("have.text", "Then thenhelloThere"); - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Then thenhelloThere", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello thenhelloThere", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello thenhelloThere", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Then thenhelloThere", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Then thenhelloThere", - ); - }); - - cy.log("Cannnot modify subbed by adding spaces to separate match"); - cy.get(cesc("#\\/subbed2_input")).type( - `{end}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow} {leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow} {enter}`, - ); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Then thenhelloThere", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello thenhelloThere", - ); - cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhelloThere"); - cy.get(cesc("#\\/subbed")).should("have.text", "Then thenhelloThere"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello thenhelloThere", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello thenhelloThere", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Then thenhelloThere", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Then thenhelloThere", - ); - }); - - cy.log( - "change original so that replacement matches original as a whole word", - ); - cy.get(cesc("#\\/orig_input")).type( - "{end}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow} {enter}", - ); - - cy.get(cesc("#\\/orig2")).should("have.text", "hello then helloThere"); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello then helloThere", - ); - cy.get(cesc("#\\/subbed")).should("have.text", "Then then helloThere"); - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Then then helloThere", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello then helloThere", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello then helloThere", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Then then helloThere", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Then then helloThere", - ); - }); - - cy.log("Cannot modify subbed due to replacement match"); - cy.get(cesc("#\\/subbed2_input")).type(`{end}nothing{enter}`); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Then then helloThere", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello then helloThere", - ); - cy.get(cesc("#\\/orig2")).should("have.text", "hello then helloThere"); - cy.get(cesc("#\\/subbed")).should("have.text", "Then then helloThere"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello then helloThere", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello then helloThere", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Then then helloThere", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Then then helloThere", - ); - }); - - cy.log("match case"); - cy.get(cesc("#\\/matchCase")).click(); - - cy.get(cesc("#\\/matchCase2")).should("have.text", "true"); - - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello then helloThere", - ); - cy.get(cesc("#\\/orig2")).should("have.text", "hello then helloThere"); - cy.get(cesc("#\\/subbed")).should("have.text", "Then then helloThere"); - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Then then helloThere", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello then helloThere", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello then helloThere", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Then then helloThere", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Then then helloThere", - ); - }); - - cy.log( - "Now cannot modify subbed due to replacement not matching original case", - ); - cy.get(cesc("#\\/subbed2_input")).type(`{end} Hello{enter}`); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Then then helloThere Hello", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello then helloThere Hello", - ); - cy.get(cesc("#\\/orig2")).should( - "have.text", - "hello then helloThere Hello", - ); - cy.get(cesc("#\\/subbed")).should( - "have.text", - "Then then helloThere Hello", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello then helloThere Hello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello then helloThere Hello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Then then helloThere Hello", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Then then helloThere Hello", - ); - }); - - cy.log("Cannot add match to subbed"); - cy.get(cesc("#\\/subbed2_input")).type(`{end} hello{enter}`); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Then then helloThere Hello", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "hello then helloThere Hello", - ); - cy.get(cesc("#\\/orig2")).should( - "have.text", - "hello then helloThere Hello", - ); - cy.get(cesc("#\\/subbed")).should( - "have.text", - "Then then helloThere Hello", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "hello then helloThere Hello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "hello then helloThere Hello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Then then helloThere Hello", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Then then helloThere Hello", - ); - }); - - cy.log("Change subbed to switch cases"); - cy.get(cesc("#\\/subbed2_input")).type( - `{home}{rightArrow}{backspace}t{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{backspace}T{enter}`, - ); - - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "then hello helloThere Hello", - ); - cy.get(cesc("#\\/orig2")).should( - "have.text", - "then hello helloThere Hello", - ); - cy.get(cesc("#\\/subbed")).should( - "have.text", - "then Then helloThere Hello", - ); - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "then Then helloThere Hello", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "then hello helloThere Hello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "then hello helloThere Hello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "then Then helloThere Hello", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "then Then helloThere Hello", - ); - }); - - cy.log("preserve case"); - cy.get(cesc("#\\/preserveCase")).click(); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "then then helloThere Hello", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "then hello helloThere Hello", - ); - cy.get(cesc("#\\/orig2")).should( - "have.text", - "then hello helloThere Hello", - ); - cy.get(cesc("#\\/subbed")).should( - "have.text", - "then then helloThere Hello", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "then hello helloThere Hello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "then hello helloThere Hello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "then then helloThere Hello", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "then then helloThere Hello", - ); - }); - - cy.log( - "Cannot change subbed since original contains effective replacement", - ); - cy.get(cesc("#\\/subbed2_input")).type(`{end} more{enter}`); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "then then helloThere Hello", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "then hello helloThere Hello", - ); - cy.get(cesc("#\\/orig2")).should( - "have.text", - "then hello helloThere Hello", - ); - cy.get(cesc("#\\/subbed")).should( - "have.text", - "then then helloThere Hello", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "then hello helloThere Hello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "then hello helloThere Hello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "then then helloThere Hello", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "then then helloThere Hello", - ); - }); - - cy.log( - "change case of match so that effective replacement is not in original", - ); - cy.get(cesc("#\\/match_input")).type( - `{home}{rightArrow}{backspace}H{enter}`, - ); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "then hello helloThere Then", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "then hello helloThere Hello", - ); - cy.get(cesc("#\\/orig2")).should( - "have.text", - "then hello helloThere Hello", - ); - cy.get(cesc("#\\/subbed")).should( - "have.text", - "then hello helloThere Then", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "then hello helloThere Hello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "then hello helloThere Hello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "then hello helloThere Then", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "then hello helloThere Then", - ); - }); - - cy.log("Can now change subbed"); - cy.get(cesc("#\\/subbed2_input")).type( - `{home}{rightArrow}{backspace}T{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{backspace}{backspace}{backspace}{backspace}{backspace}HELLO THEN{enter}`, - ); - - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "Hello HELLO THEN helloThere Hello", - ); - cy.get(cesc("#\\/orig2")).should( - "have.text", - "Hello HELLO THEN helloThere Hello", - ); - cy.get(cesc("#\\/subbed")).should( - "have.text", - "Then HELLO THEN helloThere Then", - ); - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Then HELLO THEN helloThere Then", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "Hello HELLO THEN helloThere Hello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "Hello HELLO THEN helloThere Hello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Then HELLO THEN helloThere Then", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Then HELLO THEN helloThere Then", - ); - }); - - cy.log( - "change case of match so that effective replacement is again in original", - ); - cy.get(cesc("#\\/match_input")).type( - `{home}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{backspace}{backspace}{backspace}{backspace}ELLO{enter}`, - ); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Hello THEN THEN helloThere Hello", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "Hello HELLO THEN helloThere Hello", - ); - cy.get(cesc("#\\/orig2")).should( - "have.text", - "Hello HELLO THEN helloThere Hello", - ); - cy.get(cesc("#\\/subbed")).should( - "have.text", - "Hello THEN THEN helloThere Hello", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "Hello HELLO THEN helloThere Hello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "Hello HELLO THEN helloThere Hello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Hello THEN THEN helloThere Hello", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Hello THEN THEN helloThere Hello", - ); - }); - - cy.log("Cannot change subbed"); - cy.get(cesc("#\\/subbed2_input")).type(`{end} ineffective{enter}`); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Hello THEN THEN helloThere Hello", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "Hello HELLO THEN helloThere Hello", - ); - cy.get(cesc("#\\/orig2")).should( - "have.text", - "Hello HELLO THEN helloThere Hello", - ); - cy.get(cesc("#\\/subbed")).should( - "have.text", - "Hello THEN THEN helloThere Hello", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "Hello HELLO THEN helloThere Hello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "Hello HELLO THEN helloThere Hello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Hello THEN THEN helloThere Hello", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Hello THEN THEN helloThere Hello", - ); - }); - - cy.log("change original so no longer has effective replacement"); - cy.get(cesc("#\\/orig_input")).type( - `{home}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{backspace}{backspace}{backspace}hen{enter}`, - ); - - cy.get(cesc("#\\/orig2")).should( - "have.text", - "Hello HELLO Then helloThere Hello", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "Hello HELLO Then helloThere Hello", - ); - cy.get(cesc("#\\/subbed")).should( - "have.text", - "Hello THEN Then helloThere Hello", - ); - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Hello THEN Then helloThere Hello", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "Hello HELLO Then helloThere Hello", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "Hello HELLO Then helloThere Hello", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Hello THEN Then helloThere Hello", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Hello THEN Then helloThere Hello", - ); - }); - - cy.log("Can change subbed once more"); - cy.get(cesc("#\\/subbed2_input")).type( - `{end}{backspace}{backspace}{backspace}{backspace}{backspace}THEN{enter}`, - ); - - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "Hello HELLO Then helloThere HELLO", - ); - cy.get(cesc("#\\/orig2")).should( - "have.text", - "Hello HELLO Then helloThere HELLO", - ); - cy.get(cesc("#\\/subbed")).should( - "have.text", - "Hello THEN Then helloThere THEN", - ); - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Hello THEN Then helloThere THEN", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "Hello HELLO Then helloThere HELLO", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "Hello HELLO Then helloThere HELLO", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Hello THEN Then helloThere THEN", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Hello THEN Then helloThere THEN", - ); - }); - - cy.log("Cannot add match to subbed"); - cy.get(cesc("#\\/subbed2_input")).type(`{end} HELLO{enter}`); - - cy.get(cesc("#\\/subbed2_input")).should( - "have.value", - "Hello THEN Then helloThere THEN", - ); - cy.get(cesc("#\\/orig_input")).should( - "have.value", - "Hello HELLO Then helloThere HELLO", - ); - cy.get(cesc("#\\/orig2")).should( - "have.text", - "Hello HELLO Then helloThere HELLO", - ); - cy.get(cesc("#\\/subbed")).should( - "have.text", - "Hello THEN Then helloThere THEN", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].stateValues.value).eq( - "Hello HELLO Then helloThere HELLO", - ); - expect(stateVariables["/orig2"].stateValues.value).eq( - "Hello HELLO Then helloThere HELLO", - ); - expect(stateVariables["/subbed"].stateValues.value).eq( - "Hello THEN Then helloThere THEN", - ); - expect(stateVariables["/subbed2"].stateValues.value).eq( - "Hello THEN Then helloThere THEN", - ); - }); - }); - - it("substitute with incomplete attributes does nothing", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x+1 - x+1 - x+1 - hello - hello - hello - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc("#\\/m3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - - cy.get(cesc("#\\/t1")).should("have.text", "hello"); - cy.get(cesc("#\\/t2")).should("have.text", "hello"); - cy.get(cesc("#\\/t3")).should("have.text", "hello"); - }); - - it("rounding with math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - ax+847.29418392+5y - ax+847.29418392+5y - ax+847.29418392+5y - ax+847.29418392+5y - -

- $orig - - - $orig - - - $orig - - - $orig -

-

- - -

- - -

- $origDig3 - - - $origDig3 - - - $origDig3 - - - $origDig3 -

-

- - -

- -

- $origDec3 - - - $origDec3 - - - $origDec3 - - - $origDec3 -

-

- - -

- -

- $origPad - - - $origPad - - - $origPad - - - $origPad -

-

- - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847.29+5y"); - }); - cy.get(cesc("#\\/e1Dig4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.07395x+847.3+5y"); - }); - cy.get(cesc("#\\/e1Dec4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847.2942+5y"); - }); - cy.get(cesc("#\\/e1Pad") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847.29+5.00y"); - }); - cy.get(cesc("#\\/e1Dig4a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.07395x+847.3+5y"); - }); - cy.get(cesc("#\\/e1Dec4a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847.2942+5y"); - }); - - cy.get(cesc("#\\/e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847+5y"); - }); - cy.get(cesc("#\\/e2Dig4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.07395x+847.3+5y"); - }); - cy.get(cesc("#\\/e2Dec4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847.2942+5y"); - }); - cy.get(cesc("#\\/e2Pad") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847+5.00y"); - }); - cy.get(cesc("#\\/e2Dig4a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.07395x+847.3+5y"); - }); - cy.get(cesc("#\\/e2Dec4a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847.2942+5y"); - }); - - cy.get(cesc("#\\/e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.074x+847.294+5y"); - }); - cy.get(cesc("#\\/e3Dig4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.07395x+847.3+5y"); - }); - cy.get(cesc("#\\/e3Dec4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847.2942+5y"); - }); - cy.get(cesc("#\\/e3Pad") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.074x+847.294+5.000y"); - }); - cy.get(cesc("#\\/e3Dig4a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.07395x+847.3+5y"); - }); - cy.get(cesc("#\\/e3Dec4a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847.2942+5y"); - }); - - cy.get(cesc("#\\/e4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847.29+5.00y"); - }); - cy.get(cesc("#\\/e4Dig4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.07395x+847.3+5.000y"); - }); - cy.get(cesc("#\\/e4Dec4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847.2942+5.0000y"); - }); - cy.get(cesc("#\\/e4NoPad") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847.29+5y"); - }); - cy.get(cesc("#\\/e4Dig4a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.07395x+847.3+5.000y"); - }); - cy.get(cesc("#\\/e4Dec4a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).equal("0.0739x+847.2942+5.0000y"); - }); - }); -});